def has_bcs_service(self, access_token, project_id, request_namespace): """判断是否开启容器服务 开启后就不能关闭,所以缓存很久,默认30天 """ cache_key = f"BK_DEVOPS_BCS:HAS_BCS_SERVICE:{project_id}" project = region.get(cache_key, expiration_time=3600 * 24 * 30) if not project or not isinstance(project, FancyDict): result = paas_cc.get_project(access_token, project_id) project = result.get("data") or {} # coes: container orchestration engines project['coes'] = project['kind'] try: from backend.container_service.projects.utils import get_project_kind # k8s类型包含kind为1(bcs k8s)或其它属于k8s的编排引擎 project['kind'] = get_project_kind(project['kind']) except ImportError: pass project = FancyDict(project) if request_namespace in SKIP_REQUEST_NAMESPACE: # 如果是SKIP_REQUEST_NAMESPACE,有更新接口,不判断kind if project.get("cc_app_id") != 0: region.set(cache_key, project) elif project.get("cc_app_id") != 0: region.set(cache_key, project) else: # 其他抛出没有开启容器服务 raise error_codes.NoBCSService() return project
def has_bcs_service(self, access_token, project_id, request_namespace): """判断是否开启容器服务 开启后就不能关闭,所以缓存很久,默认30天 """ cache_key = f'BK_DEVOPS_BCS:HAS_BCS_SERVICE:{project_id}' project = region.get(cache_key, expiration_time=3600 * 24 * 30) if not project or not isinstance(project, FancyDict): result = paas_cc.get_project(access_token, project_id) project = result.get('data') or {} project = FancyDict(project) if request_namespace in SKIP_REQUEST_NAMESPACE: # 如果是SKIP_REQUEST_NAMESPACE,有更新接口,不判断kind if project.get('cc_app_id') != 0 and project.get( 'kind') in ClusterType: region.set(cache_key, project) elif project.get('kind') in ClusterType: # 如果已经开启容器服务,判断是否cc_app_id再缓存 if project.get('cc_app_id') != 0: region.set(cache_key, project) else: # 其他抛出没有开启容器服务 raise error_codes.NoBCSService() return project
def get_cc_app_id(access_token, project_id): resp = paas_cc.get_project(access_token, project_id) if not resp.get("code"): return "" data = resp.get('data') return data.get("cc_app_id", "")
def get_or_add_private_repos(self, project_id, user): project = paas_cc.get_project(access_token=self.access_token, project_id=project_id) if settings.HELM_HAS_ABILITY_SUPPLY_CHART_REPO_SERVICE: # 2. add/get private repo for project private_repo = add_repo( target_project_id=project_id, name=project["data"]["english_name"], provider_name="chartmuseum", url="http://localhost/", # merely provide schema user=user, ) else: repo_auth = { "type": "basic", "role": "admin", "credentials": { "username": settings.HELM_MERELY_REPO_USERNAME, "password": settings.HELM_MERELY_REPO_PASSWORD, } } english_name = project['data']['english_name'] url = '%s/chartrepo/%s/' % (settings.HELM_MERELY_REPO_URL, english_name) private_repo = add_plain_repo(target_project_id=project_id, name=english_name, url=url, repo_auth=repo_auth) return [private_repo]
def get_k8s_context(self, request, project_id_or_code, cluster_id): """获取docker监控信息""" access_token = paas_auth.get_access_token().get("access_token") result = paas_cc.get_project(access_token, project_id_or_code) if result.get("code") != ErrorCode.NoError: raise error_codes.APIError( _("项目Code或者ID不正确: {}").format(result.get("message", ""))) project_id = result["data"]["project_id"] client = K8SClient(access_token, project_id, cluster_id, None) slz = K8SWebConsoleOpenSLZ(data=request.data, context={"client": client}) slz.is_valid(raise_exception=True) try: bcs_context = utils.get_k8s_cluster_context( client, project_id, cluster_id) except Exception as error: logger.exception("get access cluster context failed: %s", error) message = _("获取集群{}【{}】WebConsole session 信息失败").format( cluster_id, cluster_id) # 返回前端消息 raise error_codes.APIError(message) bcs_context["mode"] = k8s.ContainerDirectClient.MODE bcs_context["user_pod_name"] = slz.validated_data["pod_name"] bcs_context["project_id"] = project_id bcs_context.update(slz.validated_data) return bcs_context
def get_project_info(self, request, project_id): """获取项目信息 """ resp = paas_cc.get_project(request.user.token.access_token, project_id) if resp.get('code') != ErrorCode.NoError: raise error_codes.APIError.f(resp.get('message')) request.project = FancyDict(resp.get('data', {}))
def cached_project_info(project_code): """缓存项目类型""" result = paas_cc.get_project(request.user.token.access_token, project_code) if result['code'] != 0: return {} return result['data']
def get_project_kind(self, request, project_id): """获取项目类型,现阶段包含mesos和k8s""" project_info = paas_cc.get_project(request.user.token.access_token, project_id) if project_info.get("code") != ErrorCode.NoError: return False, APIResponse({"code": project_info.get("code", DEFAULT_ERROR_CODE), "message": _("请求出现异常!")}) if project_info.get("data", {}).get("kind") not in constants.PROJECT_KIND_LIST: return False, APIResponse({"code": ErrorCode.UserError, "message": _("该项目编排类型不正确!"), "data": None}) return True, project_info["data"]["kind"]
def retrieve(self, request, project_id, *args, **kwargs): project = paas_cc.get_project( access_token=request.user.token.access_token, project_id=project_id) project_code = project["data"]["english_name"] repo_info = self.get_private_repo_info(user=request.user, project_id=project_id, project_code=project_code) base_url = request.build_absolute_uri() base_url = base_url.split("bcs/k8s")[0] if not settings.HELM_HAS_ABILITY_SUPPLY_CHART_REPO_SERVICE: repo_url = repo_info["url"] else: repo_url = f"http://{settings.PLATFORM_REPO_DOMAIN}/{settings.HELM_REPO_ENV}/{project_code}" context = { "project_id": project_id, "chart_domain": settings.PLATFORM_REPO_DOMAIN, "helm_env": settings.HELM_REPO_ENV, "project_code": str(project_code), "username": repo_info["username"], "password": repo_info["password"], "base_url": base_url, "repo_url": repo_url, "helm_push_parameters": "", "rumpetroll_demo_url": settings.RUMPETROLL_DEMO_DOWNLOAD_URL } if settings.HELM_HAS_ABILITY_SUPPLY_CHART_REPO_SERVICE: context[ "helm_push_parameters"] = "--context-path=/{helm_env}/{project_code}".format( helm_env=settings.HELM_REPO_ENV, project_code=str(project_code)) file_prefix = 'backend/bcs_k8s/app/documentation' if request.LANGUAGE_CODE == 'en': filename = f'{file_prefix}/how-to-push-chart-en.md' else: filename = f'{file_prefix}/how-to-push-chart.md' with open( os.path.join( settings.STATIC_ROOT.split("staticfiles")[0], filename), "r") as f: template = Template(f.read()) content = template.render(**context) response = HttpResponse(content=content, content_type='text/plain; charset=UTF-8') response[ 'Content-Disposition'] = 'attachment; filename="how-to-push-helm-chart.md"' return response
def handle(self, *args, **options): access_token = bcs_perm.get_access_token().get('access_token') if not access_token: print('get access_token by paas_auth fail') return for project in ProjectDataInfo.objects.all(): result = paas_cc.get_project(access_token, project.project_id) if result['result']: project.cc_biz_id = result['data']['cc_app_id'] project.save(update_fields=['cc_biz_id']) else: print(project.project_id, result)
def info(self, request, project_id): """单个项目信息""" project_resp = paas_cc.get_project(request.user.token.access_token, project_id) if project_resp.get("code") != ErrorCode.NoError: raise error_codes.APIError(f'not found project info, {project_resp.get("message")}') data = project_resp["data"] data["created_at"], data["updated_at"] = self.normalize_create_update_time( data["created_at"], data["updated_at"] ) # 添加业务名称 data["cc_app_name"] = get_application_name(request) data["can_edit"] = self.can_edit(request, project_id) return Response(data)
def get_project_code(self, access_token, project_id): """获取project_code 缓存较长时间 """ cache_key = f'BK_DEVOPS_BCS:PROJECT_CODE:{project_id}' project_code = region.get(cache_key, expiration_time=3600 * 24 * 30) if not project_code: result = paas_cc.get_project(access_token, project_id) if result.get('code') != 0: return None project_code = result['data']['english_name'] region.set(cache_key, project_code) return project_code
def get_request_user(self, request, access_token, project_id): if settings.DEBUG: app_code, username = DEFAULT_APP_CODE, DEFAULT_USER else: app_code, username = parse_jwt_info(self.jwt_info(request)) request.user = APIUser request.user.token.access_token = access_token request.user.username = DEFAULT_USER if settings.DEBUG else username request.user.app_code = app_code result = get_project(access_token, project_id) project = result.get("data") or {} project = FancyDict(project) request.project = project
def get_project_code(self, access_token, project_id): """获取project_code 缓存较长时间 """ cache_key = f"BK_DEVOPS_BCS:PROJECT_CODE:{project_id}" project_code = region.get(cache_key, expiration_time=3600 * 24 * 30) if not project_code: # 这里的project_id对应实际的project_id或project_code, paas_cc接口兼容了两种类型的查询 result = paas_cc.get_project(access_token, project_id) if result.get("code") != 0: return None project_code = result["data"]["english_name"] region.set(cache_key, project_code) return project_code
def check_user_project(access_token, project_id, cc_app_id, jwt_info, project_code_flag=False, is_orgin_project=False): """检测用户有项目权限 """ # 针对非用户态进行特殊处理 if not jwt_info and settings.DEBUG: app_code = DEFAULT_APP_CODE else: app_code, _ = parse_jwt_info(jwt_info) if skip_authentication(app_code): resp = paas_cc.get_project(access_token, project_id) if resp.get("code") != ErrorCode.NoError: raise error_codes.APIError.f(resp.get("message", "")) data = resp.get("data") or {} if str(data.get("cc_app_id")) != str(cc_app_id): raise error_codes.CheckFailed.f("用户没有访问项目的权限,请确认", replace=True) project_kind = PROJECT_KIND_MAP.get(str(data.get("kind", ""))) if project_code_flag: project_code = data.get("english_name") project_info = data else: project_info = paas_cc.get_auth_project(access_token) # 通过cc app id过滤 if project_info.get("code") != ErrorCode.NoError: raise error_codes.APIError.f(project_info.get("message")) ret_data = [ info for info in project_info.get("data") or [] if str(info.get("cc_app_id")) == str(cc_app_id) and info["project_id"] == project_id ] if not ret_data: raise error_codes.CheckFailed.f("用户没有访问项目的权限,请确认", replace=True) project_kind = PROJECT_KIND_MAP.get(str(ret_data[0].get("kind", ""))) project_info = ret_data[0] project_code = project_info.get("english_name") # 统一处理项目类型 if not project_kind: raise error_codes.CheckFailed.f("项目类型只能为k8s/mesos,请确认", replace=True) # 直接返回原生的project信息 if is_orgin_project: return project_kind, app_code, project_info if project_code_flag: return project_kind, app_code, project_code return project_kind, app_code
def register_ns(log): # 添加default命名空间 # 如果存在则跳过 resp = paas_cc.get_cluster_namespace_list( log.token, log.project_id, log.cluster_id, desire_all_data=True ) ns_name_list = [ info["name"] for info in resp.get("data", {}).get("results") or [] if info.get("name") ] if "default" not in ns_name_list: # 获取项目编排类型,只有为k8s时,才会执行注册操作 resp = paas_cc.get_project(log.token, log.project_id) data = resp.get("data", {}) if data.get("kind") == 1: register_default_ns(log.token, log.operator, log.project_id, data.get("english_name"), log.cluster_id)
def get_project_id(self, access_token, project_id): """获取project_id 缓存较长时间 # TODO 临时使用 """ cache_key = f"BK_DEVOPS_BCS:REAL_PROJECT_ID:{project_id}" real_project_id = region.get(cache_key, expiration_time=3600 * 24 * 30) if not real_project_id: # 这里的project_id对应实际的project_id或project_code, paas_cc接口兼容了两种类型的查询 result = paas_cc.get_project(access_token, project_id) if result.get("code") != 0: return None real_project_id = result["data"]["project_id"] region.set(cache_key, real_project_id) return real_project_id
def cached_project_kind(project_code): """缓存项目类型""" result = paas_cc.get_project(request.user.token.access_token, project_code) if result['code'] != 0: return "" # 未开启容器服务 if result['data']['kind'] == 0: return "" # mesos if result['data']['kind'] != ProjectKindID: return "mesos" # 包含 k8s, tke return "k8s"
def get_bcs_context(access_token, project_id): # 获取项目相关的信息 context = {} project = paas_cc.get_project(access_token, project_id) if project.get("code") != 0: raise ValidationError("{}(project_id:{}):{}".format(_("查询项目信息出错"), project_id, project.get("message"))) project = project.get("data") or {} context["SYS_CC_APP_ID"] = project.get("cc_app_id") # TODO 以下变量未初始化到变量表中 context["SYS_PROJECT_KIND"] = ProjectKindName context["SYS_PROJECT_CODE"] = project.get("english_name") # 获取标准日志采集的dataid data_info = get_data_id_by_project_id(project_id) context["SYS_STANDARD_DATA_ID"] = data_info.get("standard_data_id") context["SYS_NON_STANDARD_DATA_ID"] = data_info.get("non_standard_data_id") return context
def get_scheduler_driver(access_token, project_id, configuration): project = paas_cc.get_project(access_token, project_id) if project.get('code') != 0 or not project.get('data'): raise error_codes.APIError.f(project.get('message')) cluster_type = ClusterType.get(project['data']['kind']) # for test # cluster_type = 'Mesos' if cluster_type == 'Kubernetes': schduler = k8s.Scheduler( access_token, project_id, configuration, kind="Kubernetes", is_rollback=True) elif cluster_type == 'Mesos': schduler = mesos.Scheduler( access_token, project_id, configuration, kind="Mesos", is_rollback=True) else: raise NotImplementedError("only support k8s and mesos") return schduler
def project_info(self): """ { "cc_app_id": 764, "cc_app_name": "blueking", } """ if not self.access_token and self.ignore_empty_access_token: return self.context.get("project_info", dict()) resp = paas_cc.get_project(self.access_token, self.project_id) if resp.get('code') != 0: logger.error( "查询project的信息出错(project_id:{project_id}):{message}".format( project_id=self.project_id, message=resp.get('message'))) return None return resp.get('data')
def refine_project_field(self, access_token, field_name, kwargs): if field_name not in kwargs: return result = paas_cc.get_project(access_token, kwargs[field_name]) if result.get("code") != ErrorCode.NoError: raise error_codes.APIError( _("项目Code或者ID不正确: {}").format(result.get("message", ""))) if self.project_field_name == "project_code": field_value = result["data"]["english_name"] elif self.project_field_name == "project_id": field_value = result["data"]["project_id"] else: field_value = kwargs[field_name] kwargs[self.project_field_name] = field_value self.kwargs[self.project_field_name] = field_value kwargs.pop(field_name, "") self.kwargs.pop(field_name, "")
def collect_system_variable(access_token, project_id, namespace_id): sys_variables = {} # 获取标准日志采集的dataid data_info = get_data_id_by_project_id(project_id) sys_variables['SYS_STANDARD_DATA_ID'] = data_info.get('standard_data_id') sys_variables['SYS_NON_STANDARD_DATA_ID'] = data_info.get('non_standard_data_id') resp = paas_cc.get_project(access_token, project_id) if resp.get('code') != 0: logger.error( "查询project的信息出错(project_id:{project_id}):{message}".format( project_id=project_id, message=resp.get('message') ) ) project_info = resp["data"] sys_variables["SYS_CC_APP_ID"] = project_info["cc_app_id"] sys_variables['SYS_PROJECT_KIND'] = project_info["kind"] sys_variables['SYS_PROJECT_CODE'] = project_info["english_name"] resp = paas_cc.get_namespace(access_token, project_id, namespace_id) if resp.get('code') != 0: logger.error( "查询命名空间的信息出错(namespace_id:{project_id}-{namespace_id}):{message}".format( namespace_id=namespace_id, project_id=project_id, message=resp.get('message') ) ) namespace_info = resp["data"] sys_variables["SYS_NAMESPACE"] = namespace_info["name"] sys_variables["SYS_CLUSTER_ID"] = namespace_info["cluster_id"] sys_variables["SYS_PROJECT_ID"] = namespace_info["project_id"] # SYS_JFROG_DOMAIN # SYS_NON_STANDARD_DATA_ID # 获取镜像地址 jfrog_domain = paas_cc.get_jfrog_domain(access_token, project_id, sys_variables['SYS_CLUSTER_ID']) sys_variables['SYS_JFROG_DOMAIN'] = jfrog_domain return sys_variables
def get_cc_app_id(access_token, project_id): resp = paas_cc.get_project(access_token, project_id) project_info = resp.get("data") or {} return str(project_info.get("cc_app_id") or "")
def get_project_code_by_id(access_token, project_id): result = paas_cc.get_project(access_token, project_id) project = result.get('data') or {} project_code = project.get('english_name', '') return project_code
def retrieve(self, request, app_id, *args, **kwargs): app = App.objects.get(id=self.app_id) project_code_cache_key = "helm_project_cache_key:%s" % self.project_id if project_code_cache_key in cache: resp = cache.get(project_code_cache_key) else: # get_project_name resp = paas_cc.get_project(self.access_token, self.project_id) if resp.get('code') != 0: logger.error( "查询project的信息出错(project_id:{project_id}):{message}".format( project_id=self.project_id, message=resp.get('message'))) return Response({ "code": 500, "message": _("后台接口异常,根据项目ID获取项目英文名失败!") }) cache.set(project_code_cache_key, resp, 60 * 15) project_code = resp["data"]["english_name"] check_cluster_perm(user=request.user, project_id=app.project_id, cluster_id=app.cluster_id, request=request) kubeconfig = bcs_utils_client.get_kubectl_config_context( access_token=self.access_token, project_id=app.project_id, cluster_id=app.cluster_id) base_url = get_base_url(request) try: with tempfile.NamedTemporaryFile("w") as f: f.write(kubeconfig) f.flush() data = collect_resource_status(base_url=base_url, kubeconfig=f.name, app=app, project_code=project_code) except DashboardExecutionError as e: message = "get helm app status failed, error_no: {error_no}\n{output}".format( error_no=e.error_no, output=e.output) return Response({ "code": 400, "message": message, }) except DashboardError as e: message = "get helm app status failed, dashboard ctl error: {err}".format( err=e) logger.exception(message) return Response({ "code": 400, "message": message, }) except Exception as e: message = "get helm app status failed, {err}".format(err=e) logger.exception(message) return Response({ "codee": 500, "message": message, }) response = { "status": data, "app": { "transitioning_action": app.transitioning_action, "transitioning_on": app.transitioning_on, "transitioning_result": app.transitioning_result, "transitioning_message": app.transitioning_message, }, } return Response(response)
def validate_project_id(self, user, project_id): result = paas_cc.get_project(user.token.access_token, project_id) if result.get('code') != 0: raise PermissionDenied("project not found")
def get_project(access_token, project_id): return paas_cc.get_project(access_token, project_id)