def docker_pull(self, namespace, repos): # Test pull # Docker -> Index resp = requests.get('{0}/v1/repositories/{1}/{2}/images'.format( self.index_endpoint, namespace, repos), auth=tuple(self.user_credentials), headers={'X-Docker-Token': 'true'}) self.assertEqual(resp.status_code, 200) token = resp.headers.get('x-docker-token') # Here we should use the 'X-Endpoints' returned in a real environment # Docker -> Registry resp = requests.get('{0}/v1/repositories/{1}/{2}/tags/latest'.format( self.registry_endpoint, namespace, repos), headers={'Authorization': 'Token ' + token}) self.assertEqual(resp.status_code, 200, resp.text) self.cookies = resp.cookies # Docker -> Registry image_id = json.loads(resp.text) resp = requests.get('{0}/v1/images/{1}/ancestry'.format( self.registry_endpoint, image_id), cookies=self.cookies) self.update_cookies(resp) self.assertEqual(resp.status_code, 200, resp.text) ancestry = json.loads(resp.text) # We got the ancestry, let's fetch all the images there for image_id in ancestry: json_data, checksum, blob = self.fetch_image(image_id) # check queried checksum and local computed checksum from the image # are the same tmpfile = StringIO.StringIO() tmpfile.write(blob) tmpfile.seek(0) computed_checksum = checksums.compute_simple(tmpfile, json_data) tmpfile.close() self.assertEqual(checksum, computed_checksum) # Remove image tags resp = requests.delete('{0}/v1/repositories/{1}/{2}/tags'.format( self.registry_endpoint, namespace, repos), cookies=self.cookies) self.assertEqual(resp.status_code, 200, resp.text) self.update_cookies(resp) # Remove image_id, then parent_id store = storage.load() store.remove(os.path.join(store.images, self.image_id)) store.remove(os.path.join(store.images, self.parent_id))
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()