import logging import json from flask import abort, request, jsonify, make_response, session from auth.decorators import process_auth from auth.permissions import (ReadRepositoryPermission, ModifyRepositoryPermission) from data import model from data.interfaces.v1 import pre_oci_model as model from endpoints.common import parse_repository_name from endpoints.decorators import anon_protect from endpoints.v1 import v1_bp from util.audit import track_and_log from util.names import TAG_ERROR, TAG_REGEX logger = logging.getLogger(__name__) @v1_bp.route('/repositories//tags', methods=['GET']) @process_auth @anon_protect @parse_repository_name() def get_tags(namespace_name, repo_name): permission = ReadRepositoryPermission(namespace_name, repo_name) if permission.can() or model.repository_is_public(namespace_name, repo_name): repo = model.get_repository(namespace_name, repo_name) if repo.kind != 'image': msg = 'This repository is for managing %s resources and not container images.' % repo.kind abort(405, message=msg, namespace=namespace_name) tags = model.list_tags(namespace_name, repo_name) tag_map = {tag.name: tag.image.docker_image_id for tag in tags} return jsonify(tag_map) abort(403) @v1_bp.route('/repositories//tags/', methods=['GET']) @process_auth @anon_protect @parse_repository_name() def get_tag(namespace_name, repo_name, tag): permission = ReadRepositoryPermission(namespace_name, repo_name) if permission.can() or model.repository_is_public(namespace_name, repo_name): repo = model.get_repository(namespace_name, repo_name) if repo.kind != 'image': msg = 'This repository is for managing %s resources and not container images.' % repo.kind abort(405, message=msg, namespace=namespace_name) image_id = model.find_image_id_by_tag(namespace_name, repo_name, tag) if image_id is None: abort(404) resp = make_response('"%s"' % image_id) resp.headers['Content-Type'] = 'application/json' return resp abort(403) @v1_bp.route('/repositories//tags/', methods=['PUT']) @process_auth @anon_protect @parse_repository_name() def put_tag(namespace_name, repo_name, tag): permission = ModifyRepositoryPermission(namespace_name, repo_name) if permission.can(): if not TAG_REGEX.match(tag): abort(400, TAG_ERROR) repo = model.get_repository(namespace_name, repo_name) if repo.kind != 'image': msg = 'This repository is for managing %s resources and not container images.' % repo.kind abort(405, message=msg, namespace=namespace_name) image_id = json.loads(request.data) model.create_or_update_tag(namespace_name, repo_name, image_id, tag) # Store the updated tag. if 'pushed_tags' not in session: session['pushed_tags'] = {} session['pushed_tags'][tag] = image_id return make_response('Created', 200) abort(403) @v1_bp.route('/repositories//tags/', methods=['DELETE']) @process_auth @anon_protect @parse_repository_name() def delete_tag(namespace_name, repo_name, tag): permission = ModifyRepositoryPermission(namespace_name, repo_name) if permission.can(): repo = model.get_repository(namespace_name, repo_name) if repo.kind != 'image': msg = 'This repository is for managing %s resources and not container images.' % repo.kind abort(405, message=msg, namespace=namespace_name) model.delete_tag(namespace_name, repo_name, tag) track_and_log('delete_tag', model.get_repository(namespace_name, repo_name), tag=tag) return make_response('Deleted', 200) abort(403)