blob: 4efc35068d8fac7a019ab66026dd7d1bf9c9cfba [file] [log] [blame]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from urlparse import urlparse
import pytest
import requests
import requests_mock
from apache.aurora.client.docker.docker_client import (
ACCEPT_HEADER,
DEFAULT_DOCKER_REGISTRY_HOST,
MANIFESTS_URL,
DockerClientException,
DockerRegistryClient,
DockerRegistryTrait
)
from apache.aurora.common.clusters import Cluster
REGISTRY_URL = 'https://registry.example.com'
NAME = 'library/ubuntu'
TAG = 'latest'
IMAGE_DIGEST = 'sha256:45bc58500fa3d3c0d67233d4a7798134b46b486af1389ca87000c543f46c3d24'
EXPECTED_REFERENCE = '%s/%s@%s' % (urlparse(REGISTRY_URL).netloc, NAME, IMAGE_DIGEST)
def test_docker_registry_trait_default():
cluster = Cluster().with_trait(DockerRegistryTrait)
assert cluster.docker_registry == DEFAULT_DOCKER_REGISTRY_HOST
def test_docker_binding_version_check_failure():
do_test_docker_binding_failure(version_success=False)
def test_docker_binding_tag_not_found():
do_test_docker_binding_failure(manifests_success=False)
def test_docker_binding_auth_token_failure():
do_test_docker_binding_failure(auth_success=False)
def do_test_docker_binding_failure(version_success=True, manifests_success=True,
auth_success=True):
with requests_mock.Mocker() as m:
mock_registry(m, need_auth_token=True, version_success=version_success,
manifests_success=manifests_success, auth_success=auth_success)
with pytest.raises(DockerClientException):
DockerRegistryClient.resolve(mock_cluster(), NAME, TAG)
def test_docker_binding_unknown_registry():
with pytest.raises(Exception):
DockerRegistryClient.resolve(mock_cluster(), NAME, TAG)
def test_docker_binding_public_repo():
do_test_docker_binding_success()
def test_docker_binding_with_auth_public_repo():
do_test_docker_binding_success(need_auth_token=True)
def do_test_docker_binding_success(need_auth_token=False):
with requests_mock.Mocker() as m:
mock_registry(m, need_auth_token=need_auth_token)
assert DockerRegistryClient.resolve(mock_cluster(), NAME, TAG) == EXPECTED_REFERENCE
def mock_version(request, context):
context.status_code = requests.codes.ok
return {}
def mock_version_not_supported(request, context):
context.status_code = requests.codes.moved_permanently
return {'error': 'version not found'}
def mock_version_with_auth(request, context):
if request.headers.get('Authorization') == 'Bearer some-token':
return mock_version(request, context)
else:
context.status_code = requests.codes.unauthorized
context.headers.update(
{'Www-Authenticate': 'Bearer realm="https://auth.docker.io/token",'
+ 'service="registry.docker.io"'})
return {'error': 'unauthorized'}
def mock_manifests(request, context):
if request.headers['Accept'] == ACCEPT_HEADER['Accept']:
context.status_code = requests.codes.ok
context.headers.update({'Docker-Content-Digest': IMAGE_DIGEST})
return {}
else:
raise Exception("Missing Accept header")
def mock_manifests_tag_failure(request, context):
context.status_code = requests.codes.moved_permanently
return {'error': 'tag not found'}
def mock_manifests_with_auth(request, context):
if request.headers.get('Authorization') == 'Bearer some-token':
return mock_manifests(request, context)
else:
context.status_code = requests.codes.unauthorized
context.headers.update(
{'Www-Authenticate': 'Bearer realm="https://auth.docker.io/token",'
+ 'service="registry.docker.io",scope="repository:library/ubuntu:*"'})
return {'error': 'unauthorized'}
def mock_token(request, context):
return {'token': 'some-token'}
def mock_token_failure(request, context):
context.status_code = requests.codes.moved_permanently
return {'error': 'token not found'}
def mock_token_with_creds(request, context):
if request.headers.get('Authorization') == 'Basic some-auth':
return mock_token(request, context)
else:
return {'token': 'wrong-token'}
def mock_registry(m, need_auth_token=False, auth_success=True,
version_success=True, manifests_success=True):
if need_auth_token:
m.register_uri('HEAD', '%s/v2/' % REGISTRY_URL,
[{'json': mock_version_with_auth if version_success else mock_version_not_supported}])
m.register_uri('GET', 'https://auth.docker.io/token?service=registry.docker.io',
[{'json': mock_token if auth_success else mock_token_failure}])
m.register_uri('HEAD', MANIFESTS_URL % (REGISTRY_URL, NAME, TAG),
[{'json': mock_manifests_with_auth if manifests_success else mock_manifests_tag_failure}])
else:
m.register_uri('HEAD', '%s/v2/' % REGISTRY_URL,
[{'json': mock_version if version_success else mock_version_not_supported}])
m.register_uri('HEAD', MANIFESTS_URL % (REGISTRY_URL, NAME, TAG),
[{'json': mock_manifests if manifests_success else mock_manifests_tag_failure}])
def mock_cluster(docker_registry=REGISTRY_URL):
return Cluster(name='smf1-test', docker_registry=docker_registry)