Esempio n. 1
0
def put_image_layer(image_id):
    try:
        json_data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return api_error('Image not found', 404)
    layer_path = store.image_layer_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(layer_path) and not store.exists(mark_path):
        return api_error('Image already exists', 409)
    input_stream = request.stream
    if request.headers.get('transfer-encoding') == 'chunked':
        # Careful, might work only with WSGI servers supporting chunked
        # encoding (Gunicorn)
        input_stream = request.environ['wsgi.input']
    store.stream_write(layer_path, input_stream)
    # FIXME(sam): Compute the checksum while uploading the image to save time
    try:
        checksum = store.get_content(store.image_checksum_path(image_id))
    except IOError:
        # We don't have a checksum stored yet, that's fine skipping the check.
        # Not removing the mark though, image is not downloadable yet.
        return response()
    if check_image_checksum(image_id, checksum, json_data) is False:
        logger.debug('put_image_layer: Wrong checksum')
        return api_error('Checksum mismatch, ignoring the layer')
    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return response()
Esempio n. 2
0
def get_post_users():
    if flask.request.method == 'GET':
        return toolkit.response('OK', 200)
    try:
        json.loads(flask.request.data)
    except json.JSONDecodeError:
        return toolkit.api_error('Error Decoding JSON', 400)
    return toolkit.response('User Created', 201)
Esempio n. 3
0
def get_post_users():
    if flask.request.method == "GET":
        return toolkit.response("OK", 200)
    try:
        json.loads(flask.request.data)
    except json.JSONDecodeError:
        return toolkit.api_error("Error Decoding JSON", 400)
    return toolkit.response("User Created", 201)
Esempio n. 4
0
def put_image_layer(image_id):
    try:
        json_data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return toolkit.api_error('Image not found', 404)
    layer_path = store.image_layer_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(layer_path) and not store.exists(mark_path):
        return toolkit.api_error('Image already exists', 409)
    input_stream = flask.request.stream
    if flask.request.headers.get('transfer-encoding') == 'chunked':
        # Careful, might work only with WSGI servers supporting chunked
        # encoding (Gunicorn)
        input_stream = flask.request.environ['wsgi.input']
    # compute checksums
    csums = []
    sr = toolkit.SocketReader(input_stream)
    tmp, store_hndlr = storage.temp_store_handler()
    sr.add_handler(store_hndlr)
    h, sum_hndlr = checksums.simple_checksum_handler(json_data)
    sr.add_handler(sum_hndlr)
    store.stream_write(layer_path, sr)

    # read layer files and cache them
    try:
        files_json = json.dumps(layers.get_image_files_from_fobj(tmp))
        layers.set_image_files_cache(image_id, files_json)
    except Exception as e:
        logger.debug('put_image_layer: Error when caching layer file-tree:'
                     '{0}'.format(e))

    csums.append('sha256:{0}'.format(h.hexdigest()))
    try:
        tmp.seek(0)
        csums.append(checksums.compute_tarsum(tmp, json_data))
    except (IOError, checksums.TarError) as e:
        logger.debug('put_image_layer: Error when computing tarsum '
                     '{0}'.format(e))
    try:
        checksum = store.get_content(store.image_checksum_path(image_id))
    except IOError:
        # We don't have a checksum stored yet, that's fine skipping the check.
        # Not removing the mark though, image is not downloadable yet.
        flask.session['checksum'] = csums
        return toolkit.response()
    # We check if the checksums provided matches one the one we computed
    if checksum not in csums:
        logger.debug('put_image_layer: Wrong checksum')
        return toolkit.api_error('Checksum mismatch, ignoring the layer')

    tmp.close()

    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return toolkit.response()
Esempio n. 5
0
def put_image_json(image_id):
    try:
        data = json.loads(request.data)
    except json.JSONDecodeError:
        pass
    if not data or not isinstance(data, dict):
        return api_error('Invalid JSON')
    for key in ['id']:
        if key not in data:
            return api_error('Missing key `{0}\' in JSON'.format(key))
    # Read the checksum
    checksum = request.headers.get('x-docker-checksum', '')
    if checksum:
        # Storing the checksum is optional at this stage
        err = store_checksum(image_id, checksum)
        if err:
            return api_error(err)
    if image_id != data['id']:
        return api_error('JSON data contains invalid id')
    if check_images_list(image_id) is False:
        return api_error('This image does not belong to the repository')
    parent_id = data.get('parent')
    if parent_id and not store.exists(store.image_json_path(data['parent'])):
        return api_error('Image depends on a non existing parent')
    json_path = store.image_json_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(json_path) and not store.exists(mark_path):
        return api_error('Image already exists', 409)
    # If we reach that point, it means that this is a new image or a retry
    # on a failed push
    store.put_content(mark_path, 'true')
    store.put_content(json_path, request.data)
    generate_ancestry(image_id, parent_id)
    return response()
Esempio n. 6
0
def put_image_layer(image_id):
    try:
        json_data = store.get_content(store.image_json_path(image_id))
        checksum = store.get_content(store.image_checksum_path(image_id))
    except IOError:
        return api_error('JSON\'s image not found', 404)
    layer_path = store.image_layer_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(layer_path) and not store.exists(mark_path):
        return api_error('Image already exists', 409)
    input_stream = request.stream
    if request.headers.get('transfer-encoding') == 'chunked':
        # Careful, might work only with WSGI servers supporting chunked
        # encoding (Gunicorn)
        input_stream = request.environ['wsgi.input']
    store.stream_write(layer_path, input_stream)
    # FIXME(sam): Compute the checksum while uploading the image to save time
    checksum_parts = checksum.split(':')
    computed_checksum = compute_image_checksum(checksum_parts[0], image_id,
            json_data)
    if computed_checksum != checksum_parts[1].lower():
        logger.debug('put_image_layer: Wrong checksum')
        return api_error('Checksum mismatch, ignoring the layer')
    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return response()
Esempio n. 7
0
def put_tag(namespace, repository, tag):
    logger.debug("[put_tag] namespace={0}; repository={1}; tag={2}".format(
                 namespace, repository, tag))
    data = None
    try:
        data = json.loads(flask.request.data)
    except json.JSONDecodeError:
        pass
    if not data or not isinstance(data, basestring):
        return toolkit.api_error('Invalid data')
    if not store.exists(store.image_json_path(data)):
        return toolkit.api_error('Image not found', 404)
    store.put_content(store.tag_path(namespace, repository, tag), data)
    sender = flask.current_app._get_current_object()
    signals.tag_created.send(sender, namespace=namespace,
                             repository=repository, tag=tag, value=data)
    # Write some meta-data about the repos
    ua = flask.request.headers.get('user-agent', '')
    data = create_tag_json(user_agent=ua)
    json_path = store.repository_tag_json_path(namespace, repository, tag)
    store.put_content(json_path, data)
    if tag == "latest":  # TODO(dustinlacewell) : deprecate this for v2
        json_path = store.repository_json_path(namespace, repository)
        store.put_content(json_path, data)
    return toolkit.response()
Esempio n. 8
0
def get_tag(namespace, repository, tag):
    data = None
    try:
        data = store.get_content(store.tag_path(namespace, repository, tag))
    except IOError:
        return api_error('Tag not found', 404)
    return response(data)
Esempio n. 9
0
def get_repositories():
    tags = []
    for namespace_path in store.list_directory(store.images):
        for repos_path in store.list_directory(namespace_path):
            for tag in store.list_directory(repos_path):
                tags.append(tag)
    return toolkit.response(tags, 200)
Esempio n. 10
0
def delete_tag(namespace, repository, tag):
    logger.debug("[delete_tag] namespace={0}; repository={1}; tag={2}".format(namespace, repository, tag))
    try:
        store.remove(store.tag_path(namespace, repository, tag))
    except OSError:
        return api_error("Tag not found", 404)
    return response()
Esempio n. 11
0
def delete_repository(namespace, repository):
    """Remove a repository from storage

    This endpoint exists in both the registry API [1] and the indexer
    API [2], but has the same semantics in each instance.  It's in the
    tags module (instead of the index module which handles most
    repository tasks) because it should be available regardless of
    whether the rest of the index-module endpoints are enabled via the
    'standalone' config setting.

    [1]: http://docs.docker.io/en/latest/reference/api/registry_api/#delete--v1-repositories-%28namespace%29-%28repository%29- # nopep8
    [2]: http://docs.docker.io/en/latest/reference/api/index_api/#delete--v1-repositories-%28namespace%29-%28repo_name%29- # nopep8
    """
    logger.debug("[delete_repository] namespace={0}; repository={1}".format(
                 namespace, repository))
    try:
        for tag_name, tag_content in get_tags(
                namespace=namespace, repository=repository):
            delete_tag(
                namespace=namespace, repository=repository, tag=tag_name)
        # TODO(wking): remove images, but may need refcounting
        store.remove(store.repository_path(
            namespace=namespace, repository=repository))
    except OSError:
        return toolkit.api_error('Repository not found', 404)
    else:
        sender = flask.current_app._get_current_object()
        signals.repository_deleted.send(
            sender, namespace=namespace, repository=repository)
    return toolkit.response()
Esempio n. 12
0
def get_properties(namespace, repo):
    logger.debug("[get_access] namespace={0}; repository={1}".format(namespace,
                 repo))
    is_private = store.is_private(namespace, repo)
    return toolkit.response({
        'access': 'private' if is_private else 'public'
    })
Esempio n. 13
0
def put_image_checksum(image_id):
    if toolkit.DockerVersion() < '0.10':
        checksum = flask.request.headers.get('X-Docker-Checksum')
    else:
        checksum = flask.request.headers.get('X-Docker-Checksum-Payload')
    if not checksum:
        return toolkit.api_error('Missing Image\'s checksum')
    if not flask.session.get('checksum'):
        return toolkit.api_error('Checksum not found in Cookie')
    if not store.exists(store.image_json_path(image_id)):
        return toolkit.api_error('Image not found', 404)
    mark_path = store.image_mark_path(image_id)
    if not store.exists(mark_path):
        return toolkit.api_error('Cannot set this image checksum', 409)
    err = store_checksum(image_id, checksum)
    if err:
        return toolkit.api_error(err)
    if checksum not in flask.session.get('checksum', []):
        logger.debug('put_image_checksum: Wrong checksum. '
                     'Provided: {0}; Expected: {1}'.format(
                         checksum, flask.session.get('checksum')))
        return toolkit.api_error('Checksum mismatch')
    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    # We trigger a task on the diff worker if it's running
    if cache.redis_conn:
        layers.diff_queue.push(image_id)
    return toolkit.response()
Esempio n. 14
0
def get_image_ancestry(image_id, headers):
    ancestry_path = store.image_ancestry_path(image_id)
    try:
        data = store.get_content(ancestry_path)
    except IOError:
        return toolkit.api_error('Image not found', 404)
    return toolkit.response(json.loads(data), headers=headers)
Esempio n. 15
0
def delete_repository(namespace, repository):
    logger.debug("[delete_repository] namespace={0}; repository={1}".format(namespace, repository))
    try:
        store.remove(store.tag_path(namespace, repository))
    except OSError:
        return api_error("Repository not found", 404)
    return response()
Esempio n. 16
0
def get_tag(namespace, repository, tag):
    logger.debug("[get_tag] namespace={0}; repository={1}; tag={2}".format(namespace, repository, tag))
    data = None
    try:
        data = store.get_content(store.tag_path(namespace, repository, tag))
    except IOError:
        return api_error("Tag not found", 404)
    return response(data)
Esempio n. 17
0
def get_repository_images(namespace, repository):
    data = None
    try:
        path = store.index_images_path(namespace, repository)
        data = store.get_content(path)
    except IOError:
        return toolkit.api_error('images not found', 404)
    headers = generate_headers(namespace, repository, 'read')
    return toolkit.response(data, 200, headers, True)
Esempio n. 18
0
def delete_repository(namespace, repository):
    logger.debug("[delete_repository] namespace={0}; repository={1}".format(
                 namespace, repository))
    try:
        store.remove(store.tag_path(namespace, repository))
        #TODO(samalba): Trigger tags_deleted signals
    except OSError:
        return toolkit.api_error('Repository not found', 404)
    return toolkit.response()
Esempio n. 19
0
def get_post_users():
    if flask.request.method == 'GET':
        return toolkit.response('OK', 200)
    try:
        data = json.loads(flask.request.data)
        if Auth.signin(data):
            return toolkit.response('OK', 200)
        else:
            cfg = config.load()
            if not cfg.allow_signup:
                return toolkit.api_error('Signup is not allowed', 400)
            else:
                if Auth.signup(data):
                    return toolkit.response('User Created', 201)
                else:
                    return toolkit.response('User Not Created', 400)
    except json.JSONDecodeError:
        return toolkit.api_error('Error Decoding JSON', 400)
Esempio n. 20
0
def get_image_json(image_id):
    try:
        data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return api_error('Image not found', 404)
    checksum_path = store.image_checksum_path(image_id)
    headers = None
    if store.exists(checksum_path):
        headers = {'X-Docker-Checksum': store.get_content(checksum_path)}
    return response(data, headers=headers, raw=True)
Esempio n. 21
0
def get_repository_json(namespace, repository):
    json_path = store.repository_json_path(namespace, repository)
    headers = {}
    data = {'last_update': None,
            'docker_version': None,
            'docker_go_version': None,
            'arch': 'amd64',
            'os': 'linux',
            'kernel': None}
    try:
        data = json.loads(store.get_content(json_path))
    except IOError:
        if mirroring.is_mirror():
            # use code 404 to trigger the source_lookup decorator.
            # TODO(joffrey): make sure this doesn't break anything or have the
            # decorator rewrite the status code before sending
            return toolkit.response(data, code=404, headers=headers)
        # else we ignore the error, we'll serve the default json declared above
    return toolkit.response(data, headers=headers)
Esempio n. 22
0
def put_image_layer(image_id):
    try:
        json_data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return toolkit.api_error("Image not found", 404)
    layer_path = store.image_layer_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(layer_path) and not store.exists(mark_path):
        return toolkit.api_error("Image already exists", 409)
    input_stream = flask.request.stream
    if flask.request.headers.get("transfer-encoding") == "chunked":
        # Careful, might work only with WSGI servers supporting chunked
        # encoding (Gunicorn)
        input_stream = flask.request.environ["wsgi.input"]
    # compute checksums
    csums = []
    sr = toolkit.SocketReader(input_stream)
    tmp, store_hndlr = storage.temp_store_handler()
    sr.add_handler(store_hndlr)
    h, sum_hndlr = checksums.simple_checksum_handler(json_data)
    sr.add_handler(sum_hndlr)
    store.stream_write(layer_path, sr)
    csums.append("sha256:{0}".format(h.hexdigest()))
    try:
        tmp.seek(0)
        csums.append(checksums.compute_tarsum(tmp, json_data))
        tmp.close()
    except (IOError, checksums.TarError) as e:
        logger.debug("put_image_layer: Error when computing tarsum " "{0}".format(e))
    try:
        checksum = store.get_content(store.image_checksum_path(image_id))
    except IOError:
        # We don't have a checksum stored yet, that's fine skipping the check.
        # Not removing the mark though, image is not downloadable yet.
        flask.session["checksum"] = csums
        return toolkit.response()
    # We check if the checksums provided matches one the one we computed
    if checksum not in csums:
        logger.debug("put_image_layer: Wrong checksum")
        return toolkit.api_error("Checksum mismatch, ignoring the layer")
    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return toolkit.response()
Esempio n. 23
0
def _get_tags(namespace, repository):
    logger.debug("[get_tags] namespace={0}; repository={1}".format(namespace,
                 repository))
    try:
        data = {tag_name: tag_content
                for tag_name, tag_content
                in get_tags(namespace=namespace, repository=repository)}
    except OSError:
        return toolkit.api_error('Repository not found', 404)
    return toolkit.response(data)
Esempio n. 24
0
def get_tags(namespace, repository):
    data = {}
    try:
        for fname in store.list_directory(store.tag_path(namespace, repository)):
            tag_name = fname.split('/').pop()
            if not tag_name.startswith('tag_'):
                continue
            data[tag_name[4:]] = store.get_content(fname)
    except OSError:
        return api_error('Repository not found', 404)
    return response(data)
Esempio n. 25
0
def delete_tag(namespace, repository, tag):
    logger.debug("[delete_tag] namespace={0}; repository={1}; tag={2}".format(
                 namespace, repository, tag))
    try:
        store.remove(store.tag_path(namespace, repository, tag))
        sender = flask.current_app._get_current_object()
        signals.tag_deleted.send(sender, namespace=namespace,
                                 repository=repository, tag=tag)
    except OSError:
        return toolkit.api_error('Tag not found', 404)
    return toolkit.response()
Esempio n. 26
0
def put_repository(namespace, repository, images=False):
    data = None
    try:
        data = json.loads(request.data)
    except json.JSONDecodeError:
        return api_error('Error Decoding JSON', 400)
    if not data or not isinstance(data, list):
        return api_error('Invalid data')
    update_index_images(namespace, repository, request.data)
    headers = generate_headers(namespace, repository, 'write')
    code = 204 if images is True else 200
    return response('', code, headers)
Esempio n. 27
0
def get_tags(namespace, repository):
    logger.debug("[get_tags] namespace={0}; repository={1}".format(namespace, repository))
    data = {}
    try:
        for fname in store.list_directory(store.tag_path(namespace, repository)):
            tag_name = fname.split("/").pop()
            if not tag_name.startswith("tag_"):
                continue
            data[tag_name[4:]] = store.get_content(fname)
    except OSError:
        return api_error("Repository not found", 404)
    return response(data)
Esempio n. 28
0
def put_repository(namespace, repository, images=False):
    data = None
    try:
        data = json.loads(flask.request.data)
    except json.JSONDecodeError:
        return toolkit.api_error('Error Decoding JSON', 400)
    if not isinstance(data, list):
        return toolkit.api_error('Invalid data')
    update_index_images(namespace, repository, flask.request.data)
    headers = generate_headers(namespace, repository, 'write')
    code = 204 if images is True else 200
    return toolkit.response('', code, headers)
Esempio n. 29
0
def put_tag(namespace, repository, tag):
    data = None
    try:
        data = json.loads(request.data)
    except json.JSONDecodeError:
        pass
    if not data or not isinstance(data, basestring):
        return api_error('Invalid data')
    if not store.exists(store.image_json_path(data)):
        return api_error('Image not found', 404)
    store.put_content(store.tag_path(namespace, repository, tag), data)
    return response()
Esempio n. 30
0
def put_image_layer(image_id):
    try:
        json_data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return api_error('Image not found', 404)
    layer_path = store.image_layer_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(layer_path) and not store.exists(mark_path):
        return api_error('Image already exists', 409)
    input_stream = request.stream
    if request.headers.get('transfer-encoding') == 'chunked':
        # Careful, might work only with WSGI servers supporting chunked
        # encoding (Gunicorn)
        input_stream = request.environ['wsgi.input']
    # compute checksums
    csums = []
    with storage.store_stream(input_stream) as f:
        try:
            csums.append(checksums.compute_simple(f, json_data))
            f.seek(0)
            csums.append(checksums.compute_tarsum(f, json_data))
        except (IOError, checksums.TarError) as e:
            logger.debug('put_image_layer: Error when computing checksum '
                         '{0}'.format(e))
        f.seek(0)
        store.stream_write(layer_path, f)
    try:
        checksum = store.get_content(store.image_checksum_path(image_id))
    except IOError:
        # We don't have a checksum stored yet, that's fine skipping the check.
        # Not removing the mark though, image is not downloadable yet.
        session['checksum'] = csums
        return response()
    # We check if the checksums provided matches one the one we computed
    if checksum not in csums:
        logger.debug('put_image_layer: Wrong checksum')
        return api_error('Checksum mismatch, ignoring the layer')
    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return response()
Esempio n. 31
0
def put_image_layer(image_id):
    try:
        json_data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return api_error('Image not found', 404)
    layer_path = store.image_layer_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(layer_path) and not store.exists(mark_path):
        return api_error('Image already exists', 409)
    input_stream = request.stream
    if request.headers.get('transfer-encoding') == 'chunked':
        # Careful, might work only with WSGI servers supporting chunked
        # encoding (Gunicorn)
        input_stream = request.environ['wsgi.input']
    # compute checksums
    csums = []
    with storage.store_stream(input_stream) as f:
        try:
            csums.append(checksums.compute_simple(f, json_data))
            f.seek(0)
            csums.append(checksums.compute_tarsum(f, json_data))
        except (IOError, checksums.TarError) as e:
            logger.debug('put_image_layer: Error when computing checksum '
                         '{0}'.format(e))
        f.seek(0)
        store.stream_write(layer_path, f)
    try:
        checksum = store.get_content(store.image_checksum_path(image_id))
    except IOError:
        # We don't have a checksum stored yet, that's fine skipping the check.
        # Not removing the mark though, image is not downloadable yet.
        session['checksum'] = csums
        return response()
    # We check if the checksums provided matches one the one we computed
    if checksum not in csums:
        logger.debug('put_image_layer: Wrong checksum')
        return api_error('Checksum mismatch, ignoring the layer')
    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return response()
Esempio n. 32
0
def get_image_files(image_id, headers):
    try:
        repository = toolkit.get_repository()
        if repository and store.is_private(*repository):
            return toolkit.api_error('Image not found', 404)
        # If no auth token found, either standalone registry or privileged
        # access. In both cases, access is always "public".
        data = layers.get_image_files_json(image_id)
        return toolkit.response(data, headers=headers, raw=True)
    except IOError:
        return toolkit.api_error('Image not found', 404)
    except tarfile.TarError:
        return toolkit.api_error('Layer format not supported', 400)
Esempio n. 33
0
def get_image_files(image_id, headers):
    try:
        repository = toolkit.get_repository()
        if repository and store.is_private(*repository):
            return toolkit.api_error('Image not found', 404)
        # If no auth token found, either standalone registry or privileged
        # access. In both cases, access is always "public".
        data = layers.get_image_files_json(image_id)
        return toolkit.response(data, headers=headers, raw=True)
    except IOError:
        return toolkit.api_error('Image not found', 404)
    except tarfile.TarError:
        return toolkit.api_error('Layer format not supported', 400)
Esempio n. 34
0
def _get_image_json(image_id, headers=None):
    if headers is None:
        headers = {}
    data = store.get_content(store.image_json_path(image_id))
    try:
        size = store.get_size(store.image_layer_path(image_id))
        headers['X-Docker-Size'] = str(size)
    except OSError:
        pass
    checksum_path = store.image_checksum_path(image_id)
    if store.exists(checksum_path):
        headers['X-Docker-Checksum'] = store.get_content(checksum_path)
    return toolkit.response(data, headers=headers, raw=True)
Esempio n. 35
0
def delete_tag(namespace, repository, tag):
    logger.debug("[delete_tag] namespace={0}; repository={1}; tag={2}".format(
        namespace, repository, tag))
    try:
        store.remove(store.tag_path(namespace, repository, tag))
        sender = current_app._get_current_object()
        tag_deleted.send(sender,
                         namespace=namespace,
                         repository=repository,
                         tag=tag)
    except OSError:
        return api_error('Tag not found', 404)
    return response()
Esempio n. 36
0
def get_repository_json(namespace, repository):
    json_path = store.repository_json_path(namespace, repository)
    data = {'last_update': None,
            'docker_version': None,
            'docker_go_version': None,
            'arch': 'amd64',
            'os': 'linux',
            'kernel': None}
    try:
        data = json.loads(store.get_content(json_path))
    except IOError:
        # We ignore the error, we'll serve the default json declared above
        pass
    return toolkit.response(data)
Esempio n. 37
0
def get_image_json(image_id, headers):
    try:
        data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return toolkit.api_error('Image not found', 404)
    try:
        size = store.get_size(store.image_layer_path(image_id))
        headers['X-Docker-Size'] = str(size)
    except OSError:
        pass
    checksum_path = store.image_checksum_path(image_id)
    if store.exists(checksum_path):
        headers['X-Docker-Checksum'] = store.get_content(checksum_path)
    return toolkit.response(data, headers=headers, raw=True)
Esempio n. 38
0
def get_tags(namespace, repository):
    logger.debug("[get_tags] namespace={0}; repository={1}".format(namespace,
                 repository))
    data = {}
    try:
        for fname in store.list_directory(store.tag_path(namespace,
                                                         repository)):
            tag_name = fname.split('/').pop()
            if not tag_name.startswith('tag_'):
                continue
            data[tag_name[4:]] = store.get_content(fname)
    except OSError:
        return api_error('Repository not found', 404)
    return response(data)
Esempio n. 39
0
def get_private_image_files(image_id, headers):
    repository = toolkit.get_repository()
    if not repository:
        # No auth token found, either standalone registry or privileged access
        # In both cases, private images are "disabled"
        return toolkit.api_error('Image not found', 404)
    try:
        if not store.is_private(*repository):
            return toolkit.api_error('Image not found', 404)
        data = layers.get_image_files_json(image_id)
        return toolkit.response(data, headers=headers, raw=True)
    except IOError:
        return toolkit.api_error('Image not found', 404)
    except tarfile.TarError:
        return toolkit.api_error('Layer format not supported', 400)
Esempio n. 40
0
def registry_status():
    retval = {'services': ['redis', 'storage'], 'failures': {}}
    retval['host'] = socket.gethostname()
    code = 200
    jobs = [gevent.spawn(job) for job in [redis_status, storage_status]]
    gevent.joinall(jobs, timeout=10)
    for job, service in zip(jobs, retval['services']):
        try:
            value = job.get()
            if value[service] != '':
                retval['failures'].update({service: value[service]})
                code = 503
        except Exception as e:
            retval['failures'].update({service: str(e)})
            code = 503
    return toolkit.response(retval, code=code)
Esempio n. 41
0
def set_properties(namespace, repo):
    logger.debug("[set_access] namespace={0}; repository={1}".format(
        namespace, repo))
    data = None
    try:
        data = json.loads(flask.request.data)
    except json.JSONDecodeError:
        pass
    if not data or not isinstance(data, dict):
        return toolkit.api_error('Invalid data')
    private_flag_path = store.private_flag_path(namespace, repo)
    if data['access'] == 'private' and not store.is_private(namespace, repo):
        store.put_content(private_flag_path, '')
    elif data['access'] == 'public' and store.is_private(namespace, repo):
        store.remove(private_flag_path)
    return toolkit.response()
Esempio n. 42
0
def put_tag(namespace, repository, tag):
    logger.debug("[put_tag] namespace={0}; repository={1}; tag={2}".format(
                 namespace, repository, tag))
    data = None
    try:
        data = json.loads(flask.request.data)
    except json.JSONDecodeError:
        pass
    if not data or not isinstance(data, basestring):
        return toolkit.api_error('Invalid data')
    if not store.exists(store.image_json_path(data)):
        return toolkit.api_error('Image not found', 404)
    store.put_content(store.tag_path(namespace, repository, tag), data)
    sender = flask.current_app._get_current_object()
    signals.tag_created.send(sender, namespace=namespace,
                             repository=repository, tag=tag, value=data)
    return toolkit.response()
Esempio n. 43
0
def get_image_diff(image_id, headers):
    try:
        repository = toolkit.get_repository()
        if repository and store.is_private(*repository):
            return toolkit.api_error('Image not found', 404)

        # first try the cache
        diff_json = layers.get_image_diff_cache(image_id)
        # it the cache misses, request a diff from a worker
        if not diff_json:
            layers.diff_queue.push(image_id)
            # empty response
            diff_json = ""

        return toolkit.response(diff_json, headers=headers, raw=True)
    except IOError:
        return toolkit.api_error('Image not found', 404)
    except tarfile.TarError:
        return toolkit.api_error('Layer format not supported', 400)
Esempio n. 44
0
def put_image_checksum(image_id):
    checksum = flask.request.headers.get('X-Docker-Checksum')
    if not checksum:
        return toolkit.api_error('Missing Image\'s checksum')
    if not flask.session.get('checksum'):
        return toolkit.api_error('Checksum not found in Cookie')
    if not store.exists(store.image_json_path(image_id)):
        return toolkit.api_error('Image not found', 404)
    mark_path = store.image_mark_path(image_id)
    if not store.exists(mark_path):
        return toolkit.api_error('Cannot set this image checksum', 409)
    err = store_checksum(image_id, checksum)
    if err:
        return toolkit.api_error(err)
    if checksum not in flask.session.get('checksum', []):
        logger.debug('put_image_layer: Wrong checksum')
        return toolkit.api_error('Checksum mismatch')
    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return toolkit.response()
Esempio n. 45
0
def put_image_json(image_id):
    try:
        data = json.loads(request.data)
    except json.JSONDecodeError:
        pass
    if not data or not isinstance(data, dict):
        return api_error('Invalid JSON')
    for key in ['id']:
        if key not in data:
            return api_error('Missing key `{0}\' in JSON'.format(key))
    # Read the checksum
    checksum = request.headers.get('x-docker-checksum', '')
    if not checksum:
        return api_error('Missing Image\'s checksum')
    checksum_parts = checksum.split(':')
    if len(checksum_parts) != 2:
        return api_error('Invalid checksum format')
    if checksum_parts[0] not in hashlib.algorithms:
        return api_error('Checksum algorithm not supported')
    # We store the checksum
    checksum_path = store.image_checksum_path(image_id)
    store.put_content(checksum_path, checksum)
    if image_id != data['id']:
        return api_error('JSON data contains invalid id')
    if check_images_list(image_id) is False:
        return api_error('This image does not belong to the repository')
    parent_id = data.get('parent')
    if parent_id and not store.exists(store.image_json_path(data['parent'])):
        return api_error('Image depends on a non existing parent')
    json_path = store.image_json_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(json_path) and not store.exists(mark_path):
        return api_error('Image already exists', 409)
    # If we reach that point, it means that this is a new image or a retry
    # on a failed push
    store.put_content(mark_path, 'true')
    store.put_content(json_path, request.data)
    generate_ancestry(image_id, parent_id)
    return response()
Esempio n. 46
0
def put_image_json(image_id):
    try:
        data = json.loads(flask.request.data)
    except json.JSONDecodeError:
        pass
    if not data or not isinstance(data, dict):
        return toolkit.api_error('Invalid JSON')
    if 'id' not in data:
        return toolkit.api_error('Missing key `id\' in JSON')
    # Read the checksum
    checksum = flask.request.headers.get('X-Docker-Checksum')
    if checksum:
        # Storing the checksum is optional at this stage
        err = store_checksum(image_id, checksum)
        if err:
            return toolkit.api_error(err)
    else:
        # We cleanup any old checksum in case it's a retry after a fail
        store.remove(store.image_checksum_path(image_id))
    if image_id != data['id']:
        return toolkit.api_error('JSON data contains invalid id')
    if check_images_list(image_id) is False:
        return toolkit.api_error('This image does not belong to the '
                                 'repository')
    parent_id = data.get('parent')
    if parent_id and not store.exists(store.image_json_path(data['parent'])):
        return toolkit.api_error('Image depends on a non existing parent')
    json_path = store.image_json_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(json_path) and not store.exists(mark_path):
        return toolkit.api_error('Image already exists', 409)
    # If we reach that point, it means that this is a new image or a retry
    # on a failed push
    store.put_content(mark_path, 'true')
    store.put_content(json_path, flask.request.data)
    generate_ancestry(image_id, parent_id)
    return toolkit.response()
Esempio n. 47
0
def get_search():
    return toolkit.response({})
Esempio n. 48
0
def put_username(username):
    return toolkit.response('', 204)
Esempio n. 49
0
def put_image_layer(image_id):
    try:
        json_data = store.get_content(store.image_json_path(image_id))
    except IOError:
        return toolkit.api_error('Image not found', 404)
    layer_path = store.image_layer_path(image_id)
    mark_path = store.image_mark_path(image_id)
    if store.exists(layer_path) and not store.exists(mark_path):
        return toolkit.api_error('Image already exists', 409)
    input_stream = flask.request.stream
    if flask.request.headers.get('transfer-encoding') == 'chunked':
        # Careful, might work only with WSGI servers supporting chunked
        # encoding (Gunicorn)
        input_stream = flask.request.environ['wsgi.input']
    # compute checksums
    sr = toolkit.SocketReader(input_stream)
    tmp, store_hndlr = storage.temp_store_handler()
    sr.add_handler(store_hndlr)
    h, sum_hndlr = checksums.simple_checksum_handler(json_data)
    sr.add_handler(sum_hndlr)
    store.stream_write(layer_path, sr)

    # Read tar data from the tempfile
    csums = []
    tar = None
    tarsum = checksums.TarSum(json_data)
    try:
        tmp.seek(0)
        tar = tarfile.open(mode='r|*', fileobj=tmp)
        tarfilesinfo = layers.TarFilesInfo()
        for member in tar:
            tarsum.append(member, tar)
            tarfilesinfo.append(member)
        layers.set_image_files_cache(image_id, tarfilesinfo.json())
    except (IOError, tarfile.TarError) as e:
        logger.debug('put_image_layer: Error when reading Tar stream tarsum. '
                     'Disabling TarSum, TarFilesInfo. Error: {0}'.format(e))
    finally:
        if tar:
            tar.close()
        tmp.close()

    # All data have been consumed from the tempfile
    csums.append('sha256:{0}'.format(h.hexdigest()))
    csums.append(tarsum.compute())

    try:
        checksum = store.get_content(store.image_checksum_path(image_id))
    except IOError:
        # We don't have a checksum stored yet, that's fine skipping the check.
        # Not removing the mark though, image is not downloadable yet.
        flask.session['checksum'] = csums
        return toolkit.response()
    # We check if the checksums provided matches one the one we computed
    if checksum not in csums:
        logger.debug('put_image_layer: Wrong checksum')
        return toolkit.api_error('Checksum mismatch, ignoring the layer')

    # Checksum is ok, we remove the marker
    store.remove(mark_path)
    return toolkit.response()
Esempio n. 50
0
def put_repository_auth(namespace, repository):
    return response('OK')
Esempio n. 51
0
def get_properties(namespace, repo):
    logger.debug("[get_access] namespace={0}; repository={1}".format(
        namespace, repo))
    is_private = store.is_private(namespace, repo)
    return toolkit.response({'access': 'private' if is_private else 'public'})
Esempio n. 52
0
def get_image_ancestry(image_id):
    try:
        data = store.get_content(store.image_ancestry_path(image_id))
    except IOError:
        return api_error('Image not found', 404)
    return response(json.loads(data))
Esempio n. 53
0
def ping():
    return toolkit.response(
        headers={'X-Docker-Registry-Standalone': cfg.standalone is not False})
Esempio n. 54
0
def root():
    return toolkit.response('docker-registry server ({0})'.format(cfg.flavor))
Esempio n. 55
0
def put_username(username):
    return response('', 204)
Esempio n. 56
0
def get_search():
    return response({})
Esempio n. 57
0
def get_image_ancestry(image_id, headers):
    try:
        data = store.get_content(store.image_ancestry_path(image_id))
    except IOError:
        return toolkit.api_error('Image not found', 404)
    return toolkit.response(json.loads(data), headers=headers)
Esempio n. 58
0
def _delete_tag(namespace, repository, tag):
    try:
        delete_tag(namespace=namespace, repository=repository, tag=tag)
    except OSError:
        return toolkit.api_error('Tag not found', 404)
    return toolkit.response()
Esempio n. 59
0
def delete_repository_images(namespace, repository):
    # Does nothing, this file will be removed when DELETE on repos
    headers = generate_headers(namespace, repository, 'delete')
    return response('', 204, headers)