Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update docker repo api #643

Open
wants to merge 4 commits into
base: bk_repo
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 68 additions & 53 deletions bcs-app/backend/apps/depot/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

from django.utils.translation import ugettext_lazy as _

from backend.components import bk_repo
from backend.utils.error_codes import error_codes, bk_error_codes
from backend.components.enterprise.harbor import HarborClient

from backend.utils.errcodes import ErrorCode

logger = logging.getLogger(__name__)

Expand All @@ -27,17 +27,10 @@ def get_jfrog_account(access_token, project_code, project_id, is_bk=False):
"""
获取项目的镜像账号
"""
client = HarborClient(access_token, project_id, project_code)
resp = client.create_account()

# api调用失败
if resp.get('code') != 0:
message = bk_error_codes.DepotError(_("创建项目仓库账号失败"))
error_message = f'{message}, {resp.get("message", "")}'
logger.error(error_message)
raise error_codes.ComponentError(error_message)

return resp.get('data')
account = bk_repo.create_account(access_token, project_code)
# 兼容先前返回{"user": "", "password": ""}
account["user"] = account["userId"]
return account


def get_bk_jfrog_auth(access_token, project_code, project_id):
Expand Down Expand Up @@ -86,70 +79,99 @@ def trans_paging_query(query):
return query


def get_harbor_client(query):
"""镜像相关第一批API统一方法
该方法只在本文件内调用
def refine_images(images):
records = images.pop("records", [])
images["total"] = images["totalRecords"]
for record in records:
record["repo"] = record["imageName"]
record["name"] = record["imagePath"]
images["imageList"] = records
return images


def _repo_response(data):
"""兼容上层
"""
project_id = query.get('projectId')
project_code = query.get('project_code', '')
access_token = query.pop('access_token')
client = HarborClient(access_token, project_id, project_code)
return client
return {"code": ErrorCode.NoError, "data": data}


def get_public_image_list(query):
"""
获取公共镜像列表
"""
query = trans_paging_query(query)
client = get_harbor_client(query)
return client.get_public_image(**query)
images = bk_repo.query_public_images(
query["access_token"],
search_name=query.get("searchKey", ""),
page_num=query["page"],
page_size=query["pageSize"]
)
return _repo_response(refine_images(images))


def get_project_image_list(query):
"""
获取项目镜像列表
"""
query = trans_paging_query(query)
client = get_harbor_client(query)
return client.get_project_image(**query)
images = bk_repo.query_project_images(
query["access_token"],
query["project_code"],
search_name=query.get("searchKey", ""),
page_num=query["page"],
page_size=query["pageSize"]
)
return _repo_response(refine_images(images))


def get_image_tags(access_token, project_id, project_code, offset, limit, **query_params):
"""获取镜像信息和tag列表
"""
client = HarborClient(access_token, project_id, project_code)
resp = client.get_image_tags(**query_params)
# 处理返回数据(harbor 的tag列表没有做分页)
data = resp.get('data') or {}
data['has_previous'] = False
data['has_next'] = False
tags = data.get('tags') or []
for tag in tags:
project_code = "public" if query_params.get("is_public") else project_code
tags = bk_repo.query_image_tags(
access_token,
project_code,
image_name=query_params.get("imageRepo", ""),
page_num=offset,
page_size=limit
)
tags["has_previous"] = False
tags["has_next"] = False
records = tags.pop("records", [])
for record in records:
# 外部版本只有一套仓库
tag['artifactorys'] = ['PROD']
return resp
record["artifactorys"] = ["PROD"]
record["repo"] = record["imageName"]
record["name"] = record["imagePath"]
tags["tags"] = records
return _repo_response(tags)


def get_pub_or_project_image_tags(query, project_code="public"):
tags = bk_repo.query_image_tags(
query["access_token"],
project_code,
image_name=query.get("imageRepo", "")
)
records = tags.pop("records", [])
for record in records:
record["repo"] = record["imageName"]
record["name"] = record["imagePath"]
tags["tags"] = records
return _repo_response([tags])


def get_pub_image_info(query):
"""公共获镜像详情(tag列表信息)
"""
client = get_harbor_client(query)
resp = client.get_image_tags(**query)
data = resp.get('data') or {}
resp['data'] = [data]
return resp
return get_pub_or_project_image_tags(query)


def get_project_image_info(query):
"""
获取项目镜像详情(tag列表信息)
"""
client = get_harbor_client(query)
resp = client.get_image_tags(**query)
data = resp.get('data') or {}
resp['data'] = [data]
return resp
return get_pub_or_project_image_tags(query, project_code=query["project_code"])


def create_project_path_by_api(access_token, project_id, project_code):
Expand All @@ -167,11 +189,4 @@ def create_project_path_by_api(access_token, project_id, project_code):
"code": 0
}
"""
client = HarborClient(access_token, project_id, project_code)
resp = client.create_project_path()
# api调用失败
if resp.get('code') != 0:
error_message = ('%s, %s' % (bk_error_codes.DepotError(_("创建项目仓库路径失败")), resp.get('message', '')))
logger.error(error_message)
raise error_codes.ComponentError(error_message)
return True
return bk_repo.create_repo(access_token, project_code)
2 changes: 2 additions & 0 deletions bcs-app/backend/apps/depot/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class ImageDetailSLZ(serializers.Serializer):
limit = serializers.IntegerField(required=False)
offset = serializers.IntegerField(required=False)
image_repo = serializers.CharField(required=True)
# 标识是否为公共仓库镜像
is_public = serializers.BooleanField(default=False)

def validate(self, data):
if data.get('limit') is None:
Expand Down
19 changes: 16 additions & 3 deletions bcs-app/backend/apps/depot/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,12 @@ def parse_images(self, images, username):
else:
repo_prefix = f'{pro_name}/'
for i in images:
if i.get("name"):
name = i["name"]
else:
name = i.get("repo").split(repo_prefix)[-1] if pro_name else i.get("repo")
data_list.append({
'name': i.get('repo').split(repo_prefix)[-1] if pro_name else i.get('repo'),
'name': name,
"repo": i.get("repo", ""),
"deployBy": i.get("createdBy", ""),
"type": i.get("type", ""),
Expand Down Expand Up @@ -185,6 +189,12 @@ class AvailableImage(FinalizeResponseMixin, views.APIView):
"""
"""

def get_image_path(self, image):
image_path = image.get("imagePath")
if not image_path:
image_path = image.get("repo")
return image_path

def get(self, request, project_id):
image_list = []
# 获取公共镜像
Expand All @@ -197,8 +207,9 @@ def get(self, request, project_id):
pub_image_list = pub_image_data.get('imageList', [])
for _pub in pub_image_list:
_repo = _pub.get('repo')
image_path = self.get_image_path(_pub)
image_list.append({
'name': _repo.split(settings.DEPOT_PREFIX)[-1] if settings.DEPOT_PREFIX else _repo,
"name": image_path.split(settings.DEPOT_PREFIX)[-1] if settings.DEPOT_PREFIX else image_path,
'value': _repo,
'is_pub': True
})
Expand All @@ -222,8 +233,9 @@ def get(self, request, project_id):
else:
repo_prefix = f'{pro_name}/'
for _pub in pro_image_list:
image_path = self.get_image_path(_pub)
image_list.append({
'name': _pub.get('repo').split(repo_prefix)[-1] if pro_name else _pub.get('repo'),
"name": image_path.split(repo_prefix)[-1] if pro_name else image_path,
'value': _pub.get('repo'),
'is_pub': False
})
Expand Down Expand Up @@ -309,6 +321,7 @@ def get_image_detail(self, request, project_id):
'imageRepo': self.slz.data['image_repo'],
'tagStart': offset,
'tagLimit': limit,
"is_public": self.slz.data["is_public"]
}
resp = api.get_image_tags(access_token, project_id, project_code, offset, limit, **query_params)
return response.Response(resp)
87 changes: 87 additions & 0 deletions bcs-app/backend/components/bk_repo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
#
# Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available.
# Copyright (C) 2017-2019 THL A29 Limited, a Tencent company. All rights reserved.
# Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://opensource.org/licenses/MIT
#
# 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.
#
import json
import logging

from django.conf import settings

from backend.utils.requests import bk_post
from backend.utils.decorators import parse_response_data

logger = logging.getLogger(__name__)

# 镜像API在apigw上注册的地址
BK_REPO_API_PREFIX = f"{settings.BK_REPO_API_PREFIX}/{settings.BK_REPO_STAG}"
IMAGE_API_PREFIX = f"{BK_REPO_API_PREFIX}/dockerapi/api/image"
REPO_API_PREFIX = f"{BK_REPO_API_PREFIX}/dockerapi/api/repo"


def _headers(access_token):
return {
"X-BKAPI-AUTHORIZATION": json.dumps({
"access_token": access_token
})
}


def api_request(access_token, url, data=None):
return bk_post(url, json=data, headers=_headers(access_token))


def query_public_images(access_token, search_name=None, page_num=1, page_size=100):
"""查询公共仓库镜像
"""
url = f"{IMAGE_API_PREFIX}/queryPublicImage"
data = {
"searchKey": search_name,
"pageNumber": page_num,
"pageSize": page_size
}
return api_request(access_token, url, data=data)


def query_project_images(access_token, project_code, search_name=None, page_num=1, page_size=100):
"""查询项目下的镜像
"""
url = f"{IMAGE_API_PREFIX}/queryProjectImage"
data = {
"projectId": project_code,
"searchKey": search_name,
"pageNumber": page_num,
"pageSize": page_size
}
return api_request(access_token, url, data=data)


def query_image_tags(access_token, project_code, image_name, page_num=1, page_size=100):
url = f"{IMAGE_API_PREFIX}/queryImageTag"
data = {
"projectId": project_code,
"imageRepo": image_name,
"pageNumber": page_num,
"pageSize": page_size
}
return api_request(access_token, url, data=data)


def create_repo(access_token, project_code):
"""创建仓库
"""
url = f"{REPO_API_PREFIX}/create/{project_code}"
return api_request(access_token, url)


def create_account(access_token, project_code):
url = f"{REPO_API_PREFIX}/account/create/{project_code}"
return api_request(access_token, url)
5 changes: 5 additions & 0 deletions bcs-app/backend/settings/ce/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,15 @@ def configure_workers(*args, **kwargs):
BCS_CC_API_PRE_URL = f"{APIGW_HOST}/api/apigw/bcs_cc/prod"

BK_IAM_HOST = os.environ.get("BKAPP_IAM_HOST")

# BCS IAM MIGRATION相关,用于初始资源数据到权限中心
APP_CODE = APP_ID
SECRET_KEY = APP_TOKEN
BK_IAM_SYSTEM_ID = APP_ID
BK_IAM_MIGRATION_APP_NAME = "bcs_iam_migration"
BK_IAM_RESOURCE_API_HOST = BK_PAAS_INNER_HOST or "http://paas.service.consul"
BK_IAM_INNER_HOST = BK_IAM_HOST

# bk repo api prefix
BK_REPO_API_PREFIX = f"{APIGW_HOST}/api/apigw/bkrepo"
BK_REPO_STAG = "prod"