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()
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()
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()
def get_image_json(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". return _get_image_json(image_id, headers) except IOError: return toolkit.api_error('Image not found', 404)
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()
def get_private_image_json(image_id): 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) return _get_image_json(image_id) except IOError: return toolkit.api_error('Image not found', 404)
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)
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)
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()
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)
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(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()
def get_image_layer(image_id, headers): try: bytes_range = None if store.supports_bytes_range: headers['Accept-Ranges'] = 'bytes' bytes_range = _parse_bytes_range() 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". return _get_image_layer(image_id, headers, bytes_range) except IOError: return toolkit.api_error('Image not found', 404)
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)
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)
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()
def _get_image_layer(image_id, headers=None, bytes_range=None): if headers is None: headers = {} try: accel_uri_prefix = cfg.nginx_x_accel_redirect path = store.image_layer_path(image_id) if accel_uri_prefix: if isinstance(store, storage.local.LocalStorage): accel_uri = '/'.join([accel_uri_prefix, path]) headers['X-Accel-Redirect'] = accel_uri logger.debug('send accelerated {0} ({1})'.format( accel_uri, headers)) return flask.Response('', headers=headers) else: logger.warn('nginx_x_accel_redirect config set,' ' but storage is not LocalStorage') status = None if bytes_range: status = 206 headers['Content-Range'] = '{0}-{1}/*'.format(*bytes_range) return flask.Response(store.stream_read(path, bytes_range), headers=headers, status=status) except IOError: return toolkit.api_error('Image not found', 404)
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)
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()
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()
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()
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()
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)
def get_private_image_layer(image_id): try: headers = None bytes_range = None if store.supports_bytes_range: headers['Accept-Ranges'] = 'bytes' bytes_range = _parse_bytes_range() 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) if not store.is_private(*repository): return toolkit.api_error('Image not found', 404) return _get_image_layer(image_id, headers, bytes_range) except IOError: return toolkit.api_error('Image not found', 404)
def get_post_users(): if request.method == 'GET': return response('OK', 200) try: json.loads(request.data) except json.JSONDecodeError: return api_error('Error Decoding JSON', 400) return response('User Created', 201)
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()
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)
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()
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)
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()
def get_repository_images(namespace, repository): data = None try: path = store.index_images_path(namespace, repository) data = store.get_content(path) except IOError: return api_error('images not found', 404) headers = generate_headers(namespace, repository, 'read') return response(data, 200, headers, True)
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()
def _get_tags(namespace, repository): logger.debug("[get_tags] namespace={0}; repository={1}".format( namespace, repository)) try: data = dict((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)
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)
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)
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)
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()
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)
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)
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()
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)
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()
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)
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()
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()
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)