Exemple #1
0
    def post(self, request, project_id, version_id):
        version_entity = validate_version_id(project_id,
                                             version_id,
                                             is_version_entity_retrun=True)
        template_id = version_entity.template_id

        project_kind = request.project.kind
        self.slz = InstanceNamespaceSLZ(data=request.data,
                                        context={'project_kind': project_kind})
        self.slz.is_valid(raise_exception=True)
        slz_data = self.slz.data

        if 'instance_entity' not in slz_data:
            raise ValidationError(_("请选择要实例化的模板"))
        instance_entity = slz_data['instance_entity']

        # 根据template_id 查询已经被实例化过的 ns
        exist_instance_id = VersionInstance.objects.filter(
            template_id=template_id, is_deleted=False).values_list('id',
                                                                   flat=True)
        filter_ns = InstanceConfig.objects.filter(
            instance_id__in=exist_instance_id,
            is_deleted=False,
            is_bcs_success=True).exclude(ins_state=InsState.NO_INS.value)

        exist_ns = []
        # 查询每类资源已经实例化的ns,求合集,这些已经实例化过的ns不能再被实例化
        for cate in instance_entity:
            cate_data = instance_entity[cate]
            cate_name_list = [
                i.get('name') for i in cate_data if i.get('name')
            ]
            cate_ns = filter_ns.filter(category=cate, name__in=cate_name_list)
            exist_ns.extend(list(cate_ns))

        ns_resources = {}
        for inst_config in exist_ns:
            ns_id = int(inst_config.namespace)

            # HPA只通过模板集管理,可以重试实例化(apply操作)
            if inst_config.category == K8sResourceName.K8sHPA.value:
                continue

            if ns_id not in ns_resources:
                ns_resources[ns_id] = [
                    inst_config.category,
                ]
            else:
                ns_resources[ns_id].append(inst_config.category)

        for ns_id, resources in ns_resources.items():
            ns_resources[ns_id] = list(set(resources))

        return Response({
            "code": 0,
            "message": "OK",
            "data": {
                "ns_resources": ns_resources
            }
        })
Exemple #2
0
    def preview_config(self, request, project_id):
        project_kind = request.project.kind
        serializer = PreviewInstanceSLZ(data=request.data, context={'project_kind': project_kind})
        serializer.is_valid(raise_exception=True)
        slz_data = serializer.data

        # 验证 version_id 是否属于该项目
        version_id = slz_data['version_id']
        show_version_id = slz_data['show_version_id']

        template, version_entity = validate_version_id(
            project_id, version_id, is_return_all=True, show_version_id=show_version_id
        )
        # 验证用户是否有使用权限
        perm = bcs_perm.Templates(request, project_id, template.id, template.name)
        perm.can_use(raise_exception=True)

        template_id = version_entity.template_id
        version = version_entity.version
        tem_instance_entity = version_entity.get_version_instance_resource_ids

        # 验证前端传过了的预览资源是否在该版本的资源
        req_instance_entity = slz_data.get('instance_entity') or {}
        instance_entity = validate_instance_entity(req_instance_entity, tem_instance_entity)

        access_token = self.request.user.token.access_token
        username = self.request.user.username

        namespace = slz_data['namespace']
        lb_info = slz_data.get('lb_info', {})
        # 验证关联lb情况下,lb 是否都已经选中
        service_id_list = instance_entity.get('service') or []
        v_res, err_list, err_msg = validate_lb_info_by_version_id(
            access_token, project_id, version_entity, [namespace], lb_info, service_id_list
        )
        if not v_res:
            return Response({"code": 400, "message": err_msg, "data": err_list})

        # 查询当前命名空间的变量信息
        variable_dict = slz_data.get('variable_info', {}).get(namespace) or {}
        params = {
            "instance_id": "instanceID",
            "version_id": version_id,
            "show_version_id": show_version_id,
            "template_id": template_id,
            "version": version,
            "project_id": project_id,
            "access_token": access_token,
            "username": username,
            "lb_info": lb_info,
            "variable_dict": variable_dict,
            "is_preview": True,
        }
        data = preview_config_json(namespace, instance_entity, **params)
        return Response({"code": 0, "message": "OK", "data": data})
Exemple #3
0
    def post(self, request, project_id):
        """实例化模板"""
        self.project_id = project_id
        version_id = request.data.get('version_id')
        show_version_id = request.data.get('show_version_id')

        template, version_entity = validate_version_id(
            project_id,
            version_id,
            is_return_all=True,
            show_version_id=show_version_id)
        # 验证用户是否有模板集实例化权限
        perm_ctx = TemplatesetPermCtx(username=request.user.username,
                                      project_id=project_id,
                                      template_id=template.id)
        TemplatesetPermission().can_instantiate(perm_ctx)

        self.template_id = version_entity.template_id
        tem_instance_entity = version_entity.get_version_instance_resource_ids

        project_kind = request.project.kind
        self.slz = VersionInstanceCreateOrUpdateSLZ(
            data=request.data, context={'project_kind': project_kind})
        self.slz.is_valid(raise_exception=True)
        slz_data = self.slz.data

        # 验证前端传过了的预览资源是否在该版本的资源
        req_instance_entity = slz_data.get('instance_entity') or {}
        self.instance_entity = validate_instance_entity(
            req_instance_entity, tem_instance_entity)

        namespaces = slz_data['namespaces']
        ns_list = namespaces.split(',') if namespaces else []

        access_token = self.request.user.token.access_token
        username = self.request.user.username

        # 判断 template 下 前台传过来的 namespace 是否已经实例化过
        res, ns_name_list, namespace_dict = validate_ns_by_tempalte_id(
            self.template_id, ns_list, access_token, project_id,
            req_instance_entity)
        if not res:
            return Response({
                "code":
                400,
                "message":
                _("以下命名空间已经实例化过,不能再实例化\n{}").format("\n".join(ns_name_list)),
                "data":
                ns_name_list,
            })

        slz_data['ns_list'] = ns_list
        slz_data['instance_entity'] = self.instance_entity
        slz_data['template_id'] = self.template_id
        slz_data['project_id'] = project_id
        slz_data['version_id'] = version_id
        slz_data['show_version_id'] = show_version_id

        result = handle_all_config(slz_data,
                                   access_token,
                                   username,
                                   project_kind=request.project.kind)
        instance_entity = slz_data.get("instance_entity")
        all_tmpl_name_dict = self.get_tmpl_name(instance_entity)

        # 添加操作记录
        temp_name = version_entity.get_template_name()
        for i in result['success']:
            TemplatesetAuditor(audit_ctx=AuditContext(
                project_id=project_id,
                user=username,
                resource=temp_name,
                resource_id=self.template_id,
                extra=self.instance_entity,
                description=_("实例化模板集[{}]命名空间[{}]").format(
                    temp_name, i['ns_name']),
                activity_type=ActivityType.Add,
                activity_status=ActivityStatus.Succeed,
            )).log_raw()

        failed_ns_name_list = []
        failed_msg = []
        is_show_failed_msg = False
        # 针对createError的触发后台任务轮训
        if result.get('failed'):
            check_instance_status.delay(
                request.user.token.access_token,
                project_id,
                request.project.get("kind"),
                all_tmpl_name_dict,
                result['failed'],
            )
        for i in result['failed']:
            if i['res_type']:
                description = _("实例化模板集[{}]命名空间[{}],在实例化{}时失败,错误消息:{}").format(
                    temp_name, i['ns_name'], i['res_type'], i['err_msg'])
                failed_ns_name_list.append(
                    _("{}(实例化{}时)").format(i['ns_name'], i['res_type']))
            else:
                description = _("实例化模板集[{}]命名空间[{}]失败,错误消息:{}").format(
                    temp_name, i['ns_name'], i['err_msg'])
                failed_ns_name_list.append(i['ns_name'])
                if i.get('show_err_msg'):
                    failed_msg.append(i['err_msg'])
                    is_show_failed_msg = True

            TemplatesetAuditor(audit_ctx=AuditContext(
                project_id=project_id,
                user=username,
                resource=temp_name,
                resource_id=self.template_id,
                extra=self.instance_entity,
                description=description,
                activity_type=ActivityType.Add,
                activity_status=ActivityStatus.Failed,
            )).log_raw()

            if is_show_failed_msg:
                msg = '\n'.join(failed_msg)
            else:
                msg = _("以下命名空间实例化失败,\n{},请联系集群管理员解决").format(
                    "\n".join(failed_ns_name_list))
            if failed_ns_name_list:
                return Response({
                    "code": 400,
                    "message": msg,
                    "data": failed_ns_name_list
                })

        return Response({
            "code": 0,
            "message": "OK",
            "data": {
                "version_id": version_id,
                "template_id": self.template_id,
            },
        })
Exemple #4
0
    def preview_config(self, request, project_id):
        project_kind = request.project.kind
        serializer = PreviewInstanceSLZ(data=request.data,
                                        context={'project_kind': project_kind})
        serializer.is_valid(raise_exception=True)
        slz_data = serializer.data

        # 验证 version_id 是否属于该项目
        version_id = slz_data['version_id']
        show_version_id = slz_data['show_version_id']

        template, version_entity = validate_version_id(
            project_id,
            version_id,
            is_return_all=True,
            show_version_id=show_version_id)

        # 验证用户是否有模板集的实例化权限
        perm_ctx = TemplatesetPermCtx(username=request.user.username,
                                      project_id=project_id,
                                      template_id=template.id)
        TemplatesetPermission().can_instantiate(perm_ctx)

        template_id = version_entity.template_id
        version = version_entity.version
        tem_instance_entity = version_entity.get_version_instance_resource_ids

        # 验证前端传过了的预览资源是否在该版本的资源
        req_instance_entity = slz_data.get('instance_entity') or {}
        instance_entity = validate_instance_entity(req_instance_entity,
                                                   tem_instance_entity)

        access_token = self.request.user.token.access_token
        username = self.request.user.username

        namespace_id = slz_data['namespace']
        lb_info = slz_data.get('lb_info', {})

        resp = paas_cc.get_namespace(access_token, project_id, namespace_id)
        if resp.get('code') != 0:
            return Response({
                'code':
                400,
                'message':
                f"查询命名空间(namespace_id:{project_id}-{namespace_id})出错:{resp.get('message')}",
            })

        namespace_info = resp['data']
        perm_ctx = NamespaceScopedPermCtx(
            username=username,
            project_id=project_id,
            cluster_id=namespace_info['cluster_id'],
            name=namespace_info['name'],
        )
        NamespaceScopedPermission().can_use(perm_ctx)

        # 查询当前命名空间的变量信息
        variable_dict = slz_data.get('variable_info',
                                     {}).get(namespace_id) or {}
        params = {
            "instance_id": "instanceID",
            "version_id": version_id,
            "show_version_id": show_version_id,
            "template_id": template_id,
            "version": version,
            "project_id": project_id,
            "access_token": access_token,
            "username": username,
            "lb_info": lb_info,
            "variable_dict": variable_dict,
            "is_preview": True,
        }
        data = preview_config_json(namespace_id, instance_entity, **params)
        return Response({"code": 0, "message": "OK", "data": data})
Exemple #5
0
    def post(self, request, project_id):
        """实例化模板"""
        # 参数验证
        self.project_id = project_id
        version_id = request.data.get('version_id')
        show_version_id = request.data.get('show_version_id')

        template, version_entity = validate_version_id(
            project_id, version_id, is_return_all=True, show_version_id=show_version_id
        )
        # 验证用户是否有使用权限
        perm = bcs_perm.Templates(request, project_id, template.id, template.name)
        perm.can_use(raise_exception=True)

        self.template_id = version_entity.template_id
        tem_instance_entity = version_entity.get_version_instance_resource_ids

        project_kind = request.project.kind
        self.slz = VersionInstanceCreateOrUpdateSLZ(data=request.data, context={'project_kind': project_kind})
        self.slz.is_valid(raise_exception=True)
        slz_data = self.slz.data

        # 验证前端传过了的预览资源是否在该版本的资源
        req_instance_entity = slz_data.get('instance_entity') or {}
        self.instance_entity = validate_instance_entity(req_instance_entity, tem_instance_entity)

        namespaces = slz_data['namespaces']
        ns_list = namespaces.split(',') if namespaces else []

        access_token = self.request.user.token.access_token
        username = self.request.user.username

        # 验证关联lb情况下,lb 是否都已经选中
        service_id_list = self.instance_entity.get('service') or []
        v_res, err_list, err_msg = validate_lb_info_by_version_id(
            access_token, project_id, version_entity, ns_list, slz_data.get('lb_info', {}), service_id_list
        )
        if not v_res:
            return Response({"code": 400, "message": err_msg, "data": err_list})

        # 判断 template 下 前台传过来的 namespace 是否已经实例化过
        res, ns_name_list, namespace_dict = validate_ns_by_tempalte_id(
            self.template_id, ns_list, access_token, project_id, req_instance_entity
        )
        if not res:
            return Response(
                {
                    "code": 400,
                    "message": _("以下命名空间已经实例化过,不能再实例化\n{}").format("\n".join(ns_name_list)),
                    "data": ns_name_list,
                }
            )

        slz_data['ns_list'] = ns_list
        slz_data['instance_entity'] = self.instance_entity
        slz_data['template_id'] = self.template_id
        slz_data['project_id'] = project_id
        slz_data['version_id'] = version_id
        slz_data['show_version_id'] = show_version_id

        result = handle_all_config(slz_data, access_token, username, project_kind=request.project.kind)
        instance_entity = slz_data.get("instance_entity")
        all_tmpl_name_dict = self.get_tmpl_name(instance_entity)

        # 添加操作记录
        temp_name = version_entity.get_template_name()
        for i in result['success']:
            client.ContextActivityLogClient(
                project_id=project_id,
                user=username,
                resource_type="template",
                resource=temp_name,
                resource_id=self.template_id,
                extra=json.dumps(self.instance_entity),
                description=_("实例化模板集[{}]命名空间[{}]").format(temp_name, i['ns_name']),
            ).log_add(activity_status="succeed")

        failed_ns_name_list = []
        failed_msg = []
        is_show_failed_msg = False
        # 针对createError的触发后台任务轮训
        if result.get('failed'):
            check_instance_status.delay(
                request.user.token.access_token,
                project_id,
                request.project.get("kind"),
                all_tmpl_name_dict,
                result['failed'],
            )
        for i in result['failed']:
            if i['res_type']:
                description = _("实例化模板集[{}]命名空间[{}],在实例化{}时失败,错误消息:{}").format(
                    temp_name, i['ns_name'], i['res_type'], i['err_msg']
                )
                failed_ns_name_list.append(_("{}(实例化{}时)").format(i['ns_name'], i['res_type']))
            else:
                description = _("实例化模板集[{}]命名空间[{}]失败,错误消息:{}").format(temp_name, i['ns_name'], i['err_msg'])
                failed_ns_name_list.append(i['ns_name'])
                if i.get('show_err_msg'):
                    failed_msg.append(i['err_msg'])
                    is_show_failed_msg = True

            client.ContextActivityLogClient(
                project_id=project_id,
                user=username,
                resource_type="template",
                resource=temp_name,
                resource_id=self.template_id,
                extra=json.dumps(self.instance_entity),
                description=description,
            ).log_add(activity_status="failed")

            if is_show_failed_msg:
                msg = '\n'.join(failed_msg)
            else:
                msg = _("以下命名空间实例化失败,\n{},请联系集群管理员解决").format("\n".join(failed_ns_name_list))
            if failed_ns_name_list:
                return Response({"code": 400, "message": msg, "data": failed_ns_name_list})

        return Response(
            {
                "code": 0,
                "message": "OK",
                "data": {
                    "version_id": version_id,
                    "template_id": self.template_id,
                },
            }
        )
Exemple #6
0
    def post(self, request, project_id, version_id):
        version_entity = validate_version_id(project_id, version_id, is_version_entity_retrun=True)

        project_kind = request.project.kind
        self.slz = VariableNamespaceSLZ(data=request.data, context={'project_kind': project_kind})
        self.slz.is_valid(raise_exception=True)
        slz_data = self.slz.data

        if 'instance_entity' not in slz_data:
            raise ValidationError(_("请选择要实例化的模板"))
        instance_entity = slz_data['instance_entity']

        lb_services = []
        key_list = []
        for cate in instance_entity:
            cate_data = instance_entity[cate]
            cate_id_list = [i.get('id') for i in cate_data if i.get('id')]
            # 查询这些配置文件的变量名
            for _id in cate_id_list:
                if cate in ['metric']:
                    config = self.get_metric_confg(_id)
                else:
                    try:
                        resource = MODULE_DICT.get(cate).objects.get(id=_id)
                    except Exception:
                        continue
                    config = resource.config
                search_list = check_var_by_config(config)
                key_list.extend(search_list)
                # mesos Deployment 需要再查询 Application 的配置文件
                if cate in ['deployment']:
                    deployment_app = VersionedEntity.get_application_by_deployment_id(version_id, _id)
                    deployment_app_config = deployment_app.config
                    _search_list = check_var_by_config(deployment_app_config)
                    key_list.extend(_search_list)

            # mesos service 查询需要lb的列表
            if project_kind == 2 and cate == 'service':
                lb_services = version_entity.get_lb_services_by_ids(cate_id_list)

        key_list = list(set(key_list))
        variable_dict = {}
        if key_list:
            # 验证变量名是否符合规范,不符合抛出异常,否则后续用 django 模板渲染变量也会抛出异常

            var_objects = Variable.objects.filter(Q(project_id=project_id) | Q(project_id=0))

            access_token = request.user.token.access_token
            namespace_res = paas_cc.get_namespace_list(access_token, project_id, limit=ALL_LIMIT)
            namespace_data = namespace_res.get('data', {}).get('results') or []
            namespace_dict = {str(i['id']): i['cluster_id'] for i in namespace_data}

            ns_list = slz_data['namespaces'].split(',') if slz_data['namespaces'] else []
            for ns_id in ns_list:
                _v_list = []
                for _key in key_list:
                    key_obj = var_objects.filter(key=_key)
                    if key_obj.exists():
                        _obj = key_obj.first()
                        # 只显示自定义变量
                        if _obj.category == 'custom':
                            cluster_id = namespace_dict.get(ns_id, 0)
                            _v_list.append(
                                {"key": _obj.key, "name": _obj.name, "value": _obj.get_show_value(cluster_id, ns_id)}
                            )
                    else:
                        _v_list.append({"key": _key, "name": _key, "value": ""})
                variable_dict[ns_id] = _v_list
        return Response(
            {"code": 0, "message": "OK", "data": {"lb_services": lb_services, "variable_dict": variable_dict}}
        )