Kaydet (Commit) baaa3e3b authored tarafından Joffrey F's avatar Joffrey F

Merge pull request #802 from docker/785-docker_config_env

Use DOCKER_CONFIG environment variable to look up auth config
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
import base64 import base64
import fileinput
import json import json
import logging import logging
import os import os
...@@ -132,78 +131,79 @@ def parse_auth(entries): ...@@ -132,78 +131,79 @@ def parse_auth(entries):
return conf return conf
def find_config_file(config_path=None):
environment_path = os.path.join(
os.environ.get('DOCKER_CONFIG'),
os.path.basename(DOCKER_CONFIG_FILENAME)
) if os.environ.get('DOCKER_CONFIG') else None
paths = [
config_path, # 1
environment_path, # 2
os.path.join(os.path.expanduser('~'), DOCKER_CONFIG_FILENAME), # 3
os.path.join(
os.path.expanduser('~'), LEGACY_DOCKER_CONFIG_FILENAME
) # 4
]
for path in paths:
if path and os.path.exists(path):
return path
return None
def load_config(config_path=None): def load_config(config_path=None):
""" """
Loads authentication data from a Docker configuration file in the given Loads authentication data from a Docker configuration file in the given
root directory or if config_path is passed use given path. root directory or if config_path is passed use given path.
Lookup priority:
explicit config_path parameter > DOCKER_CONFIG environment variable >
~/.docker/config.json > ~/.dockercfg
""" """
conf = {}
data = None
# Prefer ~/.docker/config.json.
config_file = config_path or os.path.join(os.path.expanduser('~'),
DOCKER_CONFIG_FILENAME)
log.debug("Trying {0}".format(config_file))
if os.path.exists(config_file):
try:
with open(config_file) as f:
for section, data in six.iteritems(json.load(f)):
if section != 'auths':
continue
log.debug("Found 'auths' section")
return parse_auth(data)
log.debug("Couldn't find 'auths' section")
except (IOError, KeyError, ValueError) as e:
# Likely missing new Docker config file or it's in an
# unknown format, continue to attempt to read old location
# and format.
log.debug(e)
pass
else:
log.debug("File doesn't exist")
config_file = config_path or os.path.join(os.path.expanduser('~'),
LEGACY_DOCKER_CONFIG_FILENAME)
log.debug("Trying {0}".format(config_file)) config_file = find_config_file(config_path)
if not os.path.exists(config_file): if not config_file:
log.debug("File doesn't exist - returning empty config") log.debug("File doesn't exist")
return {} return {}
log.debug("Attempting to parse as JSON")
try: try:
with open(config_file) as f: with open(config_file) as f:
return parse_auth(json.load(f)) data = json.load(f)
except Exception as e: if data.get('auths'):
log.debug("Found 'auths' section")
return parse_auth(data)
else:
log.debug("Couldn't find 'auths' section")
f.seek(0)
return parse_auth(json.load(f))
except (IOError, KeyError, ValueError) as e:
# Likely missing new Docker config file or it's in an
# unknown format, continue to attempt to read old location
# and format.
log.debug(e) log.debug(e)
pass
# If that fails, we assume the configuration file contains a single
# authentication token for the public registry in the following format:
#
# auth = AUTH_TOKEN
# email = email@domain.com
log.debug("Attempting to parse legacy auth file format") log.debug("Attempting to parse legacy auth file format")
try: try:
data = [] data = []
for line in fileinput.input(config_file): with open(config_file) as f:
data.append(line.strip().split(' = ')[1]) for line in f.readlines():
if len(data) < 2: data.append(line.strip().split(' = ')[1])
# Not enough data if len(data) < 2:
raise errors.InvalidConfigFile( # Not enough data
'Invalid or empty configuration file!') raise errors.InvalidConfigFile(
'Invalid or empty configuration file!'
)
username, password = decode_auth(data[0]) username, password = decode_auth(data[0])
conf[INDEX_NAME] = { return {
'username': username, INDEX_NAME: {
'password': password, 'username': username,
'email': data[1], 'password': password,
'serveraddress': INDEX_URL, 'email': data[1],
'serveraddress': INDEX_URL,
}
} }
return conf
except Exception as e: except Exception as e:
log.debug(e) log.debug(e)
pass pass
......
...@@ -2387,7 +2387,7 @@ class DockerClientTest(Cleanup, base.BaseTestCase): ...@@ -2387,7 +2387,7 @@ class DockerClientTest(Cleanup, base.BaseTestCase):
f.write('auth = {0}\n'.format(auth_)) f.write('auth = {0}\n'.format(auth_))
f.write('email = sakuya@scarlet.net') f.write('email = sakuya@scarlet.net')
cfg = docker.auth.load_config(dockercfg_path) cfg = docker.auth.load_config(dockercfg_path)
self.assertTrue(docker.auth.INDEX_NAME in cfg) assert docker.auth.INDEX_NAME in cfg
self.assertNotEqual(cfg[docker.auth.INDEX_NAME], None) self.assertNotEqual(cfg[docker.auth.INDEX_NAME], None)
cfg = cfg[docker.auth.INDEX_NAME] cfg = cfg[docker.auth.INDEX_NAME]
self.assertEqual(cfg['username'], 'sakuya') self.assertEqual(cfg['username'], 'sakuya')
...@@ -2412,10 +2412,10 @@ class DockerClientTest(Cleanup, base.BaseTestCase): ...@@ -2412,10 +2412,10 @@ class DockerClientTest(Cleanup, base.BaseTestCase):
} }
with open(dockercfg_path, 'w') as f: with open(dockercfg_path, 'w') as f:
f.write(json.dumps(config)) json.dump(config, f)
cfg = docker.auth.load_config(dockercfg_path) cfg = docker.auth.load_config(dockercfg_path)
self.assertTrue(registry in cfg) assert registry in cfg
self.assertNotEqual(cfg[registry], None) self.assertNotEqual(cfg[registry], None)
cfg = cfg[registry] cfg = cfg[registry]
self.assertEqual(cfg['username'], 'sakuya') self.assertEqual(cfg['username'], 'sakuya')
...@@ -2423,6 +2423,33 @@ class DockerClientTest(Cleanup, base.BaseTestCase): ...@@ -2423,6 +2423,33 @@ class DockerClientTest(Cleanup, base.BaseTestCase):
self.assertEqual(cfg['email'], 'sakuya@scarlet.net') self.assertEqual(cfg['email'], 'sakuya@scarlet.net')
self.assertEqual(cfg.get('auth'), None) self.assertEqual(cfg.get('auth'), None)
def test_load_config_custom_config_env(self):
folder = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, folder)
dockercfg_path = os.path.join(folder, 'config.json')
registry = 'https://your.private.registry.io'
auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
config = {
registry: {
'auth': '{0}'.format(auth_),
'email': 'sakuya@scarlet.net'
}
}
with open(dockercfg_path, 'w') as f:
json.dump(config, f)
with mock.patch.dict(os.environ, {'DOCKER_CONFIG': folder}):
cfg = docker.auth.load_config(None)
assert registry in cfg
self.assertNotEqual(cfg[registry], None)
cfg = cfg[registry]
self.assertEqual(cfg['username'], 'sakuya')
self.assertEqual(cfg['password'], 'izayoi')
self.assertEqual(cfg['email'], 'sakuya@scarlet.net')
self.assertEqual(cfg.get('auth'), None)
def test_tar_with_excludes(self): def test_tar_with_excludes(self):
dirs = [ dirs = [
'foo', 'foo',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment