Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
docker-py
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
docker-py
Commits
ccbde11c
Kaydet (Commit)
ccbde11c
authored
Ock 31, 2018
tarafından
Joffrey F
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Improve separation between auth_configs and general_configs
Signed-off-by:
Joffrey F
<
joffrey@docker.com
>
üst
75e2e8ad
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
149 additions
and
111 deletions
+149
-111
build.py
docker/api/build.py
+2
-4
client.py
docker/api/client.py
+4
-1
daemon.py
docker/api/daemon.py
+2
-0
auth.py
docker/auth.py
+41
-34
config.py
docker/utils/config.py
+3
-2
decorators.py
docker/utils/decorators.py
+3
-3
api_container_test.py
tests/integration/api_container_test.py
+1
-1
base.py
tests/integration/base.py
+0
-4
api_build_test.py
tests/unit/api_build_test.py
+32
-16
auth_test.py
tests/unit/auth_test.py
+14
-38
utils_config_test.py
tests/unit/utils_config_test.py
+45
-6
utils_test.py
tests/unit/utils_test.py
+2
-2
No files found.
docker/api/build.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -300,14 +300,12 @@ class BuildApiMixin(object):
# Matches CLI behavior: https://github.com/docker/docker/blob/
# 67b85f9d26f1b0b2b240f2d794748fac0f45243c/cliconfig/
# credentials/native_store.go#L68-L83
for
registry
in
self
.
_auth_configs
.
keys
():
if
registry
==
'credsStore'
or
registry
==
'HttpHeaders'
:
continue
for
registry
in
self
.
_auth_configs
.
get
(
'auths'
,
{})
.
keys
():
auth_data
[
registry
]
=
auth
.
resolve_authconfig
(
self
.
_auth_configs
,
registry
)
else
:
auth_data
=
self
.
_auth_configs
.
copy
()
auth_data
=
self
.
_auth_configs
.
get
(
'auths'
,
{})
.
copy
()
# See https://github.com/docker/docker-py/issues/1683
if
auth
.
INDEX_NAME
in
auth_data
:
auth_data
[
auth
.
INDEX_URL
]
=
auth_data
[
auth
.
INDEX_NAME
]
...
...
docker/api/client.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -87,6 +87,7 @@ class APIClient(
"""
__attrs__
=
requests
.
Session
.
__attrs__
+
[
'_auth_configs'
,
'_general_configs'
,
'_version'
,
'base_url'
,
'timeout'
]
...
...
@@ -105,8 +106,10 @@ class APIClient(
self
.
timeout
=
timeout
self
.
headers
[
'User-Agent'
]
=
user_agent
self
.
_auth_configs
=
auth
.
load_config
()
self
.
_general_configs
=
config
.
load_general_config
()
self
.
_auth_configs
=
auth
.
load_config
(
config_dict
=
self
.
_general_configs
)
base_url
=
utils
.
parse_host
(
base_url
,
IS_WINDOWS_PLATFORM
,
tls
=
bool
(
tls
)
...
...
docker/api/daemon.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -144,6 +144,8 @@ class DaemonApiMixin(object):
response
=
self
.
_post_json
(
self
.
_url
(
'/auth'
),
data
=
req_data
)
if
response
.
status_code
==
200
:
if
'auths'
not
in
self
.
_auth_configs
:
self
.
_auth_configs
[
'auths'
]
=
{}
self
.
_auth_configs
[
registry
or
auth
.
INDEX_NAME
]
=
req_data
return
self
.
_result
(
response
,
json
=
True
)
...
...
docker/auth.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -98,11 +98,12 @@ def resolve_authconfig(authconfig, registry=None):
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
:
authdict
=
authconfig
.
get
(
'auths'
,
{})
if
registry
in
authdict
:
log
.
debug
(
"Found {0}"
.
format
(
repr
(
registry
)))
return
auth
config
[
registry
]
return
auth
dict
[
registry
]
for
key
,
conf
in
six
.
iteritems
(
auth
config
):
for
key
,
conf
in
six
.
iteritems
(
auth
dict
):
if
resolve_index_name
(
key
)
==
registry
:
log
.
debug
(
"Found {0}"
.
format
(
repr
(
key
)))
return
conf
...
...
@@ -220,7 +221,7 @@ def parse_auth(entries, raise_on_error=False):
return
conf
def
load_config
(
config_path
=
None
):
def
load_config
(
config_path
=
None
,
config_dict
=
None
):
"""
Loads authentication data from a Docker configuration file in the given
root directory or if config_path is passed use given path.
...
...
@@ -228,39 +229,45 @@ def load_config(config_path=None):
explicit config_path parameter > DOCKER_CONFIG environment variable >
~/.docker/config.json > ~/.dockercfg
"""
config_file
=
config
.
find_config_file
(
config_path
)
if
not
config_file
:
return
{}
if
not
config_dict
:
config_file
=
config
.
find_config_file
(
config_path
)
if
not
config_file
:
return
{}
try
:
with
open
(
config_file
)
as
f
:
config_dict
=
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
)
return
_load_legacy_config
(
config_file
)
res
=
{}
if
config_dict
.
get
(
'auths'
):
log
.
debug
(
"Found 'auths' section"
)
res
.
update
({
'auths'
:
parse_auth
(
config_dict
.
pop
(
'auths'
),
raise_on_error
=
True
)
})
if
config_dict
.
get
(
'credsStore'
):
log
.
debug
(
"Found 'credsStore' section"
)
res
.
update
({
'credsStore'
:
config_dict
.
pop
(
'credsStore'
)})
if
config_dict
.
get
(
'credHelpers'
):
log
.
debug
(
"Found 'credHelpers' section"
)
res
.
update
({
'credHelpers'
:
config_dict
.
pop
(
'credHelpers'
)})
if
res
:
return
res
log
.
debug
(
"Couldn't find auth-related section ; attempting to interpret"
"as auth-only file"
)
return
parse_auth
(
config_dict
)
try
:
with
open
(
config_file
)
as
f
:
data
=
json
.
load
(
f
)
res
=
{}
if
data
.
get
(
'auths'
):
log
.
debug
(
"Found 'auths' section"
)
res
.
update
(
parse_auth
(
data
[
'auths'
],
raise_on_error
=
True
))
if
data
.
get
(
'HttpHeaders'
):
log
.
debug
(
"Found 'HttpHeaders' section"
)
res
.
update
({
'HttpHeaders'
:
data
[
'HttpHeaders'
]})
if
data
.
get
(
'credsStore'
):
log
.
debug
(
"Found 'credsStore' section"
)
res
.
update
({
'credsStore'
:
data
[
'credsStore'
]})
if
data
.
get
(
'credHelpers'
):
log
.
debug
(
"Found 'credHelpers' section"
)
res
.
update
({
'credHelpers'
:
data
[
'credHelpers'
]})
if
res
:
return
res
else
:
log
.
debug
(
"Couldn't find 'auths' or 'HttpHeaders' sections"
)
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
)
def
_load_legacy_config
(
config_file
):
log
.
debug
(
"Attempting to parse legacy auth file format"
)
try
:
data
=
[]
...
...
docker/utils/config.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -57,9 +57,10 @@ def load_general_config(config_path=None):
try
:
with
open
(
config_file
)
as
f
:
return
json
.
load
(
f
)
except
Exception
as
e
:
except
(
IOError
,
ValueError
)
as
e
:
# In the case of a legacy `.dockercfg` file, we won't
# be able to load any JSON data.
log
.
debug
(
e
)
pass
log
.
debug
(
"All parsing attempts failed - returning empty config"
)
return
{}
docker/utils/decorators.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -38,10 +38,10 @@ def minimum_version(version):
def
update_headers
(
f
):
def
inner
(
self
,
*
args
,
**
kwargs
):
if
'HttpHeaders'
in
self
.
_
auth
_configs
:
if
'HttpHeaders'
in
self
.
_
general
_configs
:
if
not
kwargs
.
get
(
'headers'
):
kwargs
[
'headers'
]
=
self
.
_
auth
_configs
[
'HttpHeaders'
]
kwargs
[
'headers'
]
=
self
.
_
general
_configs
[
'HttpHeaders'
]
else
:
kwargs
[
'headers'
]
.
update
(
self
.
_
auth
_configs
[
'HttpHeaders'
])
kwargs
[
'headers'
]
.
update
(
self
.
_
general
_configs
[
'HttpHeaders'
])
return
f
(
self
,
*
args
,
**
kwargs
)
return
inner
tests/integration/api_container_test.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -161,7 +161,7 @@ class CreateContainerTest(BaseAPIIntegrationTest):
self
.
client
.
start
(
container3_id
)
info
=
self
.
client
.
inspect_container
(
res2
[
'Id'
])
self
.
assertCountEqual
(
info
[
'HostConfig'
][
'VolumesFrom'
],
vol_names
)
assert
len
(
info
[
'HostConfig'
][
'VolumesFrom'
])
==
len
(
vol_names
)
def
create_container_readonly_fs
(
self
):
ctnr
=
self
.
client
.
create_container
(
...
...
tests/integration/base.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -4,7 +4,6 @@ import unittest
import
docker
from
docker.utils
import
kwargs_from_env
import
six
from
..
import
helpers
...
...
@@ -19,9 +18,6 @@ class BaseIntegrationTest(unittest.TestCase):
"""
def
setUp
(
self
):
if
six
.
PY2
:
self
.
assertRegex
=
self
.
assertRegexpMatches
self
.
assertCountEqual
=
self
.
assertItemsEqual
self
.
tmp_imgs
=
[]
self
.
tmp_containers
=
[]
self
.
tmp_folders
=
[]
...
...
tests/unit/api_build_test.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -73,10 +73,12 @@ class BuildTest(BaseAPIClientTest):
def
test_build_remote_with_registry_auth
(
self
):
self
.
client
.
_auth_configs
=
{
'https://example.com'
:
{
'user'
:
'example'
,
'password'
:
'example'
,
'email'
:
'example@example.com'
'auths'
:
{
'https://example.com'
:
{
'user'
:
'example'
,
'password'
:
'example'
,
'email'
:
'example@example.com'
}
}
}
...
...
@@ -85,7 +87,10 @@ class BuildTest(BaseAPIClientTest):
'forcerm'
:
False
,
'remote'
:
'https://github.com/docker-library/mongo'
}
expected_headers
=
{
'X-Registry-Config'
:
auth
.
encode_header
(
self
.
client
.
_auth_configs
)}
'X-Registry-Config'
:
auth
.
encode_header
(
self
.
client
.
_auth_configs
[
'auths'
]
)
}
self
.
client
.
build
(
path
=
'https://github.com/docker-library/mongo'
)
...
...
@@ -118,32 +123,43 @@ class BuildTest(BaseAPIClientTest):
def
test_set_auth_headers_with_empty_dict_and_auth_configs
(
self
):
self
.
client
.
_auth_configs
=
{
'https://example.com'
:
{
'user'
:
'example'
,
'password'
:
'example'
,
'email'
:
'example@example.com'
'auths'
:
{
'https://example.com'
:
{
'user'
:
'example'
,
'password'
:
'example'
,
'email'
:
'example@example.com'
}
}
}
headers
=
{}
expected_headers
=
{
'X-Registry-Config'
:
auth
.
encode_header
(
self
.
client
.
_auth_configs
)}
'X-Registry-Config'
:
auth
.
encode_header
(
self
.
client
.
_auth_configs
[
'auths'
]
)
}
self
.
client
.
_set_auth_headers
(
headers
)
assert
headers
==
expected_headers
def
test_set_auth_headers_with_dict_and_auth_configs
(
self
):
self
.
client
.
_auth_configs
=
{
'https://example.com'
:
{
'user'
:
'example'
,
'password'
:
'example'
,
'email'
:
'example@example.com'
'auths'
:
{
'https://example.com'
:
{
'user'
:
'example'
,
'password'
:
'example'
,
'email'
:
'example@example.com'
}
}
}
headers
=
{
'foo'
:
'bar'
}
expected_headers
=
{
'foo'
:
'bar'
,
'X-Registry-Config'
:
auth
.
encode_header
(
self
.
client
.
_auth_configs
)}
'X-Registry-Config'
:
auth
.
encode_header
(
self
.
client
.
_auth_configs
[
'auths'
]
),
'foo'
:
'bar'
}
self
.
client
.
_set_auth_headers
(
headers
)
assert
headers
==
expected_headers
...
...
tests/unit/auth_test.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -106,11 +106,13 @@ class ResolveAuthTest(unittest.TestCase):
private_config
=
{
'auth'
:
encode_auth
({
'username'
:
'privateuser'
})}
legacy_config
=
{
'auth'
:
encode_auth
({
'username'
:
'legacyauth'
})}
auth_config
=
auth
.
parse_auth
({
'https://index.docker.io/v1/'
:
index_config
,
'my.registry.net'
:
private_config
,
'http://legacy.registry.url/v1/'
:
legacy_config
,
})
auth_config
=
{
'auths'
:
auth
.
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
):
assert
auth
.
resolve_authconfig
(
...
...
@@ -360,9 +362,8 @@ class LoadConfigTest(unittest.TestCase):
with
mock
.
patch
.
dict
(
os
.
environ
,
{
'DOCKER_CONFIG'
:
folder
}):
cfg
=
auth
.
load_config
(
None
)
assert
registry
in
cfg
assert
cfg
[
registry
]
is
not
None
cfg
=
cfg
[
registry
]
assert
registry
in
cfg
[
'auths'
]
cfg
=
cfg
[
'auths'
][
registry
]
assert
cfg
[
'username'
]
==
'sakuya'
assert
cfg
[
'password'
]
==
'izayoi'
assert
cfg
[
'email'
]
==
'sakuya@scarlet.net'
...
...
@@ -390,38 +391,13 @@ class LoadConfigTest(unittest.TestCase):
with
mock
.
patch
.
dict
(
os
.
environ
,
{
'DOCKER_CONFIG'
:
folder
}):
cfg
=
auth
.
load_config
(
None
)
assert
registry
in
cfg
assert
cfg
[
registry
]
is
not
None
cfg
=
cfg
[
registry
]
assert
registry
in
cfg
[
'auths'
]
cfg
=
cfg
[
'auths'
][
registry
]
assert
cfg
[
'username'
]
==
b
'sakuya
\xc3\xa6
'
.
decode
(
'utf8'
)
assert
cfg
[
'password'
]
==
b
'izayoi
\xc3\xa6
'
.
decode
(
'utf8'
)
assert
cfg
[
'email'
]
==
'sakuya@scarlet.net'
assert
cfg
.
get
(
'auth'
)
is
None
def
test_load_config_custom_config_env_with_headers
(
self
):
folder
=
tempfile
.
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
folder
)
dockercfg_path
=
os
.
path
.
join
(
folder
,
'config.json'
)
config
=
{
'HttpHeaders'
:
{
'Name'
:
'Spike'
,
'Surname'
:
'Spiegel'
},
}
with
open
(
dockercfg_path
,
'w'
)
as
f
:
json
.
dump
(
config
,
f
)
with
mock
.
patch
.
dict
(
os
.
environ
,
{
'DOCKER_CONFIG'
:
folder
}):
cfg
=
auth
.
load_config
(
None
)
assert
'HttpHeaders'
in
cfg
assert
cfg
[
'HttpHeaders'
]
is
not
None
cfg
=
cfg
[
'HttpHeaders'
]
assert
cfg
[
'Name'
]
==
'Spike'
assert
cfg
[
'Surname'
]
==
'Spiegel'
def
test_load_config_unknown_keys
(
self
):
folder
=
tempfile
.
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
folder
)
...
...
@@ -448,7 +424,7 @@ class LoadConfigTest(unittest.TestCase):
json
.
dump
(
config
,
f
)
cfg
=
auth
.
load_config
(
dockercfg_path
)
assert
cfg
==
{
'
scarlet.net'
:
{
}}
assert
cfg
==
{
'
auths'
:
{
'scarlet.net'
:
{}
}}
def
test_load_config_identity_token
(
self
):
folder
=
tempfile
.
mkdtemp
()
...
...
@@ -469,7 +445,7 @@ class LoadConfigTest(unittest.TestCase):
json
.
dump
(
config
,
f
)
cfg
=
auth
.
load_config
(
dockercfg_path
)
assert
registry
in
cfg
cfg
=
cfg
[
registry
]
assert
registry
in
cfg
[
'auths'
]
cfg
=
cfg
[
'auths'
][
registry
]
assert
'IdentityToken'
in
cfg
assert
cfg
[
'IdentityToken'
]
==
token
tests/unit/utils_config_test.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -69,16 +69,55 @@ class LoadConfigTest(unittest.TestCase):
folder
=
tempfile
.
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
folder
)
cfg
=
config
.
load_general_config
(
folder
)
self
.
assertTrue
(
cfg
is
not
None
)
assert
cfg
is
not
None
assert
isinstance
(
cfg
,
dict
)
assert
not
cfg
def
test_load_config
(
self
):
def
test_load_config
_custom_headers
(
self
):
folder
=
tempfile
.
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
folder
)
dockercfg_path
=
os
.
path
.
join
(
folder
,
'.dockercfg'
)
cfg
=
{
dockercfg_path
=
os
.
path
.
join
(
folder
,
'config.json'
)
config_data
=
{
'HttpHeaders'
:
{
'Name'
:
'Spike'
,
'Surname'
:
'Spiegel'
},
}
with
open
(
dockercfg_path
,
'w'
)
as
f
:
json
.
dump
(
config_data
,
f
)
cfg
=
config
.
load_general_config
(
dockercfg_path
)
assert
'HttpHeaders'
in
cfg
assert
cfg
[
'HttpHeaders'
]
==
{
'Name'
:
'Spike'
,
'Surname'
:
'Spiegel'
}
def
test_load_config_detach_keys
(
self
):
folder
=
tempfile
.
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
folder
)
dockercfg_path
=
os
.
path
.
join
(
folder
,
'config.json'
)
config_data
=
{
'detachKeys'
:
'ctrl-q, ctrl-u, ctrl-i'
}
with
open
(
dockercfg_path
,
'w'
)
as
f
:
json
.
dump
(
config_data
,
f
)
cfg
=
config
.
load_general_config
(
dockercfg_path
)
assert
cfg
==
config_data
def
test_load_config_from_env
(
self
):
folder
=
tempfile
.
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
folder
)
dockercfg_path
=
os
.
path
.
join
(
folder
,
'config.json'
)
config_data
=
{
'detachKeys'
:
'ctrl-q, ctrl-u, ctrl-i'
}
with
open
(
dockercfg_path
,
'w'
)
as
f
:
json
.
dump
(
c
fg
,
f
)
json
.
dump
(
c
onfig_data
,
f
)
self
.
assertEqual
(
config
.
load_general_config
(
dockercfg_path
),
cfg
)
with
mock
.
patch
.
dict
(
os
.
environ
,
{
'DOCKER_CONFIG'
:
folder
}):
cfg
=
config
.
load_general_config
(
None
)
assert
cfg
==
config_data
tests/unit/utils_test.py
Dosyayı görüntüle @
ccbde11c
...
...
@@ -46,7 +46,7 @@ class DecoratorsTest(unittest.TestCase):
return
headers
client
=
APIClient
()
client
.
_
auth
_configs
=
{}
client
.
_
general
_configs
=
{}
g
=
update_headers
(
f
)
assert
g
(
client
,
headers
=
None
)
is
None
...
...
@@ -55,7 +55,7 @@ class DecoratorsTest(unittest.TestCase):
'Content-type'
:
'application/json'
,
}
client
.
_
auth
_configs
=
{
client
.
_
general
_configs
=
{
'HttpHeaders'
:
sample_headers
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment