Skip to content

Commit 1dae8ef

Browse files
committed
Merge pull request #874 from aanand/fix-index.docker.io
Treat 'index.docker.io' repo names as 'docker.io'
2 parents 59f569a + 25b1884 commit 1dae8ef

File tree

3 files changed

+91
-47
lines changed

3 files changed

+91
-47
lines changed

docker/auth/auth.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
from .. import errors
2323

24-
INDEX_NAME = 'index.docker.io'
24+
INDEX_NAME = 'docker.io'
2525
INDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME)
2626
DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')
2727
LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'
@@ -41,7 +41,14 @@ def resolve_repository_name(repo_name):
4141
'Invalid index name ({0}). Cannot begin or end with a'
4242
' hyphen.'.format(index_name)
4343
)
44-
return index_name, remote_name
44+
return resolve_index_name(index_name), remote_name
45+
46+
47+
def resolve_index_name(index_name):
48+
index_name = convert_to_hostname(index_name)
49+
if index_name == 'index.'+INDEX_NAME:
50+
index_name = INDEX_NAME
51+
return index_name
4552

4653

4754
def split_repo_name(repo_name):
@@ -62,15 +69,15 @@ def resolve_authconfig(authconfig, registry=None):
6269
Returns None if no match was found.
6370
"""
6471
# Default to the public index server
65-
registry = convert_to_hostname(registry) if registry else INDEX_NAME
72+
registry = resolve_index_name(registry) if registry else INDEX_NAME
6673
log.debug("Looking for auth entry for {0}".format(repr(registry)))
6774

6875
if registry in authconfig:
6976
log.debug("Found {0}".format(repr(registry)))
7077
return authconfig[registry]
7178

7279
for key, config in six.iteritems(authconfig):
73-
if convert_to_hostname(key) == registry:
80+
if resolve_index_name(key) == registry:
7481
log.debug("Found {0}".format(repr(key)))
7582
return config
7683

@@ -82,11 +89,6 @@ def convert_to_hostname(url):
8289
return url.replace('http://', '').replace('https://', '').split('/', 1)[0]
8390

8491

85-
def encode_auth(auth_info):
86-
return base64.b64encode(auth_info.get('username', '') + b':' +
87-
auth_info.get('password', ''))
88-
89-
9092
def decode_auth(auth):
9193
if isinstance(auth, six.string_types):
9294
auth = auth.encode('ascii')
@@ -121,7 +123,7 @@ def parse_auth(entries):
121123
conf[registry] = {
122124
'username': username,
123125
'password': password,
124-
'email': entry['email'],
126+
'email': entry.get('email'),
125127
'serveraddress': registry,
126128
}
127129
return conf

tests/unit/auth_test.py

Lines changed: 78 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import tempfile
1010

1111
from docker import auth
12+
from docker.auth.auth import parse_auth
1213
from docker import errors
1314

1415
from .. import base
@@ -34,25 +35,31 @@ class ResolveRepositoryNameTest(base.BaseTestCase):
3435
def test_resolve_repository_name_hub_library_image(self):
3536
self.assertEqual(
3637
auth.resolve_repository_name('image'),
37-
('index.docker.io', 'image'),
38+
('docker.io', 'image'),
3839
)
3940

4041
def test_resolve_repository_name_dotted_hub_library_image(self):
4142
self.assertEqual(
4243
auth.resolve_repository_name('image.valid'),
43-
('index.docker.io', 'image.valid')
44+
('docker.io', 'image.valid')
4445
)
4546

4647
def test_resolve_repository_name_hub_image(self):
4748
self.assertEqual(
4849
auth.resolve_repository_name('username/image'),
49-
('index.docker.io', 'username/image'),
50+
('docker.io', 'username/image'),
5051
)
5152

5253
def test_explicit_hub_index_library_image(self):
54+
self.assertEqual(
55+
auth.resolve_repository_name('docker.io/image'),
56+
('docker.io', 'image')
57+
)
58+
59+
def test_explicit_legacy_hub_index_library_image(self):
5360
self.assertEqual(
5461
auth.resolve_repository_name('index.docker.io/image'),
55-
('index.docker.io', 'image')
62+
('docker.io', 'image')
5663
)
5764

5865
def test_resolve_repository_name_private_registry(self):
@@ -104,88 +111,105 @@ def test_invalid_index_name(self):
104111
)
105112

106113

114+
def encode_auth(auth_info):
115+
return base64.b64encode(
116+
auth_info.get('username', '').encode('utf-8') + b':' +
117+
auth_info.get('password', '').encode('utf-8'))
118+
119+
107120
class ResolveAuthTest(base.BaseTestCase):
108-
auth_config = {
109-
'https://index.docker.io/v1/': {'auth': 'indexuser'},
110-
'my.registry.net': {'auth': 'privateuser'},
111-
'http://legacy.registry.url/v1/': {'auth': 'legacyauth'}
112-
}
121+
index_config = {'auth': encode_auth({'username': 'indexuser'})}
122+
private_config = {'auth': encode_auth({'username': 'privateuser'})}
123+
legacy_config = {'auth': encode_auth({'username': 'legacyauth'})}
124+
125+
auth_config = parse_auth({
126+
'https://index.docker.io/v1/': index_config,
127+
'my.registry.net': private_config,
128+
'http://legacy.registry.url/v1/': legacy_config,
129+
})
113130

114131
def test_resolve_authconfig_hostname_only(self):
115132
self.assertEqual(
116-
auth.resolve_authconfig(self.auth_config, 'my.registry.net'),
117-
{'auth': 'privateuser'}
133+
auth.resolve_authconfig(
134+
self.auth_config, 'my.registry.net'
135+
)['username'],
136+
'privateuser'
118137
)
119138

120139
def test_resolve_authconfig_no_protocol(self):
121140
self.assertEqual(
122-
auth.resolve_authconfig(self.auth_config, 'my.registry.net/v1/'),
123-
{'auth': 'privateuser'}
141+
auth.resolve_authconfig(
142+
self.auth_config, 'my.registry.net/v1/'
143+
)['username'],
144+
'privateuser'
124145
)
125146

126147
def test_resolve_authconfig_no_path(self):
127148
self.assertEqual(
128149
auth.resolve_authconfig(
129150
self.auth_config, 'http://my.registry.net'
130-
),
131-
{'auth': 'privateuser'}
151+
)['username'],
152+
'privateuser'
132153
)
133154

134155
def test_resolve_authconfig_no_path_trailing_slash(self):
135156
self.assertEqual(
136157
auth.resolve_authconfig(
137158
self.auth_config, 'http://my.registry.net/'
138-
),
139-
{'auth': 'privateuser'}
159+
)['username'],
160+
'privateuser'
140161
)
141162

142163
def test_resolve_authconfig_no_path_wrong_secure_proto(self):
143164
self.assertEqual(
144165
auth.resolve_authconfig(
145166
self.auth_config, 'https://my.registry.net'
146-
),
147-
{'auth': 'privateuser'}
167+
)['username'],
168+
'privateuser'
148169
)
149170

150171
def test_resolve_authconfig_no_path_wrong_insecure_proto(self):
151172
self.assertEqual(
152173
auth.resolve_authconfig(
153174
self.auth_config, 'http://index.docker.io'
154-
),
155-
{'auth': 'indexuser'}
175+
)['username'],
176+
'indexuser'
156177
)
157178

158179
def test_resolve_authconfig_path_wrong_proto(self):
159180
self.assertEqual(
160181
auth.resolve_authconfig(
161182
self.auth_config, 'https://my.registry.net/v1/'
162-
),
163-
{'auth': 'privateuser'}
183+
)['username'],
184+
'privateuser'
164185
)
165186

166187
def test_resolve_authconfig_default_registry(self):
167188
self.assertEqual(
168-
auth.resolve_authconfig(self.auth_config), {'auth': 'indexuser'}
189+
auth.resolve_authconfig(self.auth_config)['username'],
190+
'indexuser'
169191
)
170192

171193
def test_resolve_authconfig_default_explicit_none(self):
172194
self.assertEqual(
173-
auth.resolve_authconfig(self.auth_config, None),
174-
{'auth': 'indexuser'}
195+
auth.resolve_authconfig(self.auth_config, None)['username'],
196+
'indexuser'
175197
)
176198

177199
def test_resolve_authconfig_fully_explicit(self):
178200
self.assertEqual(
179201
auth.resolve_authconfig(
180202
self.auth_config, 'http://my.registry.net/v1/'
181-
),
182-
{'auth': 'privateuser'}
203+
)['username'],
204+
'privateuser'
183205
)
184206

185207
def test_resolve_authconfig_legacy_config(self):
186208
self.assertEqual(
187-
auth.resolve_authconfig(self.auth_config, 'legacy.registry.url'),
188-
{'auth': 'legacyauth'}
209+
auth.resolve_authconfig(
210+
self.auth_config, 'legacy.registry.url'
211+
)['username'],
212+
'legacyauth'
189213
)
190214

191215
def test_resolve_authconfig_no_match(self):
@@ -198,26 +222,44 @@ def test_resolve_registry_and_auth_library_image(self):
198222
self.assertEqual(
199223
auth.resolve_authconfig(
200224
self.auth_config, auth.resolve_repository_name(image)[0]
201-
),
202-
{'auth': 'indexuser'},
225+
)['username'],
226+
'indexuser',
203227
)
204228

205229
def test_resolve_registry_and_auth_hub_image(self):
206230
image = 'username/image'
207231
self.assertEqual(
208232
auth.resolve_authconfig(
209233
self.auth_config, auth.resolve_repository_name(image)[0]
210-
),
211-
{'auth': 'indexuser'},
234+
)['username'],
235+
'indexuser',
236+
)
237+
238+
def test_resolve_registry_and_auth_explicit_hub(self):
239+
image = 'docker.io/username/image'
240+
self.assertEqual(
241+
auth.resolve_authconfig(
242+
self.auth_config, auth.resolve_repository_name(image)[0]
243+
)['username'],
244+
'indexuser',
245+
)
246+
247+
def test_resolve_registry_and_auth_explicit_legacy_hub(self):
248+
image = 'index.docker.io/username/image'
249+
self.assertEqual(
250+
auth.resolve_authconfig(
251+
self.auth_config, auth.resolve_repository_name(image)[0]
252+
)['username'],
253+
'indexuser',
212254
)
213255

214256
def test_resolve_registry_and_auth_private_registry(self):
215257
image = 'my.registry.net/image'
216258
self.assertEqual(
217259
auth.resolve_authconfig(
218260
self.auth_config, auth.resolve_repository_name(image)[0]
219-
),
220-
{'auth': 'privateuser'},
261+
)['username'],
262+
'privateuser',
221263
)
222264

223265
def test_resolve_registry_and_auth_unauthenticated_registry(self):

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ skipsdist=True
55
[testenv]
66
usedevelop=True
77
commands =
8-
py.test --cov=docker tests/unit/
8+
py.test --cov=docker {posargs:tests/unit}
99
deps =
1010
-r{toxinidir}/test-requirements.txt
1111
-r{toxinidir}/requirements.txt

0 commit comments

Comments
 (0)