Пример #1
0
    def get(self, request, project_id):
        """ 获取项目下所有的secrets """
        # 获取kind
        flag, project_kind = self.get_project_kind(request, project_id)
        if not flag:
            return project_kind

        cluster_dicts = self.get_project_cluster_info(request, project_id)
        cluster_data = cluster_dicts.get('results', {}) or {}

        data = []
        params = dict(request.GET.items())
        s_cate = 'secret' if project_kind == MESOS_VALUE else 'K8sSecret'
        access_token = request.user.token.access_token
        is_decode = request.GET.get('decode')
        is_decode = True if is_decode == '1' else False
        # get project namespace info
        namespace_dict = app_utils.get_ns_id_map(
            request.user.token.access_token, project_id)

        for cluster_info in cluster_data:
            cluster_id = cluster_info.get('cluster_id')
            # 当参数中集群ID存在时,判断集群ID匹配成功后,继续后续逻辑
            if params.get('cluster_id') and params['cluster_id'] != cluster_id:
                continue
            cluster_env = cluster_info.get('environment')
            code, cluster_secrets = self.get_secrets_by_cluster_id(
                request,
                params,
                project_id,
                cluster_id,
                project_kind=project_kind)
            # 单个集群错误时,不抛出异常信息
            if code != ErrorCode.NoError:
                continue
            self.handle_data(request,
                             cluster_secrets,
                             project_kind,
                             s_cate,
                             access_token,
                             project_id,
                             cluster_id,
                             is_decode,
                             cluster_env,
                             cluster_info.get('name', ''),
                             namespace_dict=namespace_dict)
            data += cluster_secrets

        # 按时间倒序排列
        data.sort(key=lambda x: x.get('createTime', ''), reverse=True)
        return APIResponse({
            "code": ErrorCode.NoError,
            "data": {
                "data": data,
                "length": len(data)
            },
            "message": "ok"
        })
Пример #2
0
 def get(self, request, project_id):
     """获取所有的命名空间
     """
     kind = self.project_kind(request)
     cluster_type, category = self.get_cluster_category(request, kind)
     all_namespaces = self.get_all_namespace(request, project_id)
     cluster_env_map = self.get_cluster_id_env(request, project_id)
     ret_data = self.compose_data(all_namespaces, cluster_env_map, cluster_type)
     return APIResponse({"data": ret_data})
Пример #3
0
    def scale_instance(
        self, request, project_id, cluster_id, ns, app_name, instance_num, kind=2, category=None, data=None
    ):  # noqa
        """扩缩容"""
        if kind == 2:
            client = MesosClient(request.user.token.access_token, project_id, cluster_id, None)
            resp = client.scale_mesos_app_instance(ns, app_name, instance_num)
        else:
            client = K8SClient(request.user.token.access_token, project_id, cluster_id, None)
            data["spec"]["replicas"] = int(instance_num)
            curr_func = getattr(client, FUNC_MAP[category] % "update")
            resp = curr_func(ns, app_name, data)

        if resp.get("code") != ErrorCode.NoError:
            return APIResponse(
                {"code": resp.get("code", DEFAULT_ERROR_CODE), "message": resp.get("message", _("请求出现异常!"))}
            )
        return APIResponse({"message": _("更新成功!")})
Пример #4
0
 def query_events(self, request, project_id, cluster_id, params):
     """查询事件
     """
     client = BCSDriver(request, project_id, cluster_id)
     resp = client.get_events(params)
     if resp.get("code") != ErrorCode.NoError:
         return APIResponse({
             "code": resp.get("code", DEFAULT_ERROR_CODE),
             "message": resp.get("message", _("请求出现异常!"))
         })
     return APIResponse({
         "data": {
             "data":
             resp.get("data", []),
             "total":
             100 if resp.get("total", 0) > 100 else resp.get("total", 0)
         }
     })
Пример #5
0
    def get_namespace_info(self, request, project_id, ns_id):
        """获取单个namespace
        """
        resp = paas_cc.get_namespace(
            request.user.token.access_token,
            project_id, ns_id
        )
        if resp.get("code") != ErrorCode.NoError:
            return False, APIResponse({
                "code": resp.get("code") or DEFAULT_ERROR_CODE,
                "message": resp.get("message")
            })
        if not resp.get("data"):
            return False, APIResponse({
                "code": 400,
                "message": _("查询记录为空!")
            })

        return True, resp["data"]
Пример #6
0
 def cancel_update_deployment(self, request, project_id, cluster_id, ns, deployment_name, kind=2):
     """取消更新
     """
     if kind == 2:
         client = MesosClient(
             request.user.token.access_token,
             project_id, cluster_id, None
         )
         resp = client.cancel_update_deployment(ns, deployment_name)
     else:
         resp = DEFAULT_RESPONSE
     if resp.get("code") != ErrorCode.NoError:
         return APIResponse({
             "code": resp.get("code", DEFAULT_ERROR_CODE),
             "message": resp.get("message", _("请求出现异常!"))
         })
     return APIResponse({
         "message": _("取消更新成功!")
     })
Пример #7
0
 def get_instances(self, request, project_id, cluster_id, kind=2):
     """拉取项目下的所有Instance"""
     if kind == 2:
         client = MesosClient(request.user.token.access_token, project_id, cluster_id, None)
         resp = client.get_mesos_app_instances()
     else:
         resp = DEFAULT_RESPONSE
     if resp.get("code") != ErrorCode.NoError:
         return False, APIResponse({"code": resp.get("code", DEFAULT_ERROR_CODE), "message": resp.get("message")})
     return True, resp["data"]
Пример #8
0
 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"]
Пример #9
0
    def get_pod_or_taskgroup(self,
                             request,
                             project_id,
                             cluster_id,
                             field=None,
                             app_name=None,
                             taskgroup_name=None,
                             ns_name=None,
                             kind=2,
                             category=None):
        """获取taskgroup或者pod
        """
        if kind == 2:
            client = MesosClient(request.user.token.access_token, project_id,
                                 cluster_id, None)
            resp = client.get_mesos_app_taskgroup(
                field=field
                or "data.containerStatuses.containerID,namespace,data.rcname",
                app_name=app_name,
                taskgroup_name=taskgroup_name,
                namespace=ns_name,
            )
        else:
            if taskgroup_name:
                pod_name = taskgroup_name
                rs_name = None
            elif app_name:
                pod_name = None
                rs_name = app_name
                if category in ["deployment", "K8sDeployment"]:
                    rs_name = self.get_k8s_rs_info(request, project_id,
                                                   cluster_id, ns_name,
                                                   app_name)
                    if not rs_name:
                        return True, []
            else:
                pod_name = None
                rs_name = None
            resp = self.get_k8s_pod_info(request,
                                         project_id,
                                         cluster_id,
                                         ns_name,
                                         category_name=rs_name,
                                         field=field,
                                         pod_name=pod_name)

        if resp.get("code") != ErrorCode.NoError:
            return False, APIResponse({
                "code":
                resp.get("code", DEFAULT_ERROR_CODE),
                "message":
                resp.get("message")
            })
        return True, resp["data"]
Пример #10
0
 def get_project_clusters(self, request, project_id):
     """查询项目下所有的集群"""
     resp = paas_cc.get_all_clusters(request.user.token.access_token, project_id, limit=1000, offset=0)
     if resp.get("code") != ErrorCode.NoError:
         return False, APIResponse({"code": resp.get("code", DEFAULT_ERROR_CODE), "message": resp.get("message")})
     # 获取集群id list
     cluster_id_list = []
     data = resp.get("data") or {}
     for info in data.get("results") or []:
         cluster_id_list.append(info["cluster_id"])
     return True, cluster_id_list
Пример #11
0
    def get_k8s_app_deploy_with_post(
        self, request, project_id, cluster_id, instance_name=None, category="application", namespace=None, field=None
    ):
        """获取k8s下application和deployment状态"""
        client = K8SClient(request.user.token.access_token, project_id, cluster_id, None)
        curr_func = getattr(client, "%s_with_post" % (FUNC_MAP[category] % "get"))
        params = {"name": instance_name, "namespace": namespace, "field": ",".join(field)}
        resp = retry_requests(curr_func, params=params)
        if resp.get("code") != ErrorCode.NoError:
            return False, APIResponse({"code": resp.get("code") or DEFAULT_ERROR_CODE, "message": resp.get("message")})

        return True, resp
Пример #12
0
    def get(self, request, project_id):
        """获取项目下的所有Ingress
        """
        project_kind = request.project.kind
        project_kind_name = ClusterType.get(project_kind)

        if project_kind_name != 'Kubernetes':
            raise error_codes.CheckFailed.f("K8S项目才有Ingress", replace=True)

        cluster_dicts = self.get_project_cluster_info(request, project_id)
        cluster_data = cluster_dicts.get('results', {}) or {}

        # 获取命名空间的id
        namespace_dict = app_utils.get_ns_id_map(
            request.user.token.access_token, project_id)

        s_cate = 'K8sIngress'
        is_decode = False
        params = {}
        access_token = request.user.token.access_token
        data = []
        for cluster_info in cluster_data:
            cluster_id = cluster_info.get('cluster_id')
            cluster_env = cluster_info.get('environment')
            code, cluster_data = self.get_ingress_by_cluser_id(
                request, params, project_id, cluster_id)
            # 单个集群错误时,不抛出异常信息
            if code != ErrorCode.NoError:
                continue
            self.handle_data(request,
                             cluster_data,
                             project_kind,
                             s_cate,
                             access_token,
                             project_id,
                             cluster_id,
                             is_decode,
                             cluster_env,
                             cluster_info.get('name', ''),
                             namespace_dict=namespace_dict)
            data += cluster_data

        # 按时间倒序排列
        data.sort(key=lambda x: x.get('createTime', ''), reverse=True)

        return APIResponse({
            "code": ErrorCode.NoError,
            "data": {
                "data": data,
                "length": len(data)
            },
            "message": "ok"
        })
Пример #13
0
    def get(self, request, project_id, muster_id):
        """获取命名空间
        """
        # 获取参数
        group_by = request.GET.get('group_by') or "env_type"
        category = request.GET.get("category")
        show_version_name = request.GET.get('show_version_name')
        res_name = request.GET.get('res_name')
        perm_can_use = request.GET.get('perm_can_use')
        if perm_can_use == '1':
            perm_can_use = True
        else:
            perm_can_use = False

        # 前端的category转换为后台需要的类型
        if category != 'ALL':
            project_kind = request.project.kind
            category = get_real_category(project_kind, category)

        if category != 'ALL' and category not in MODULE_DICT:
            raise error_codes.CheckFailed.f(u"category: %s 不存在" % category)
        # 获取被占用的ns,没有处于删除中和已删除
        ns_id_list = self.get_active_ns(
            muster_id, show_version_name, category, res_name)
        # 查询ns信息
        results = self.get_ns_info(request, project_id, ns_id_list)
        # 解析&排序
        cluster_env_map = self.get_cluster_env_map(request, project_id)
        results = filter(lambda x: x["id"] in ns_id_list, results)
        results = [{'name': k,
                    'cluster_name': cluster_env_map.get(k, {}).get('cluster_name', k),
                    'environment_name': "正式" if cluster_env_map.get(k, {}).get(
                        'cluster_env_str', '') == 'prod' else "测试",
                    'results': sorted(
                        list(v), key=lambda x: x['id'], reverse=True)}
                   for k, v in groupby(sorted(results, key=lambda x: x[group_by]),
                                       key=lambda x: x[group_by])]
        # ordering = [i.value for i in constants.EnvType]
        # results = sorted(results, key=lambda x: ordering.index(x['name']))
        ret_data = []
        for info in results:
            for item in (info["results"] or []):
                item["muster_id"] = muster_id
                item["environment"] = cluster_env_map.get(item["cluster_id"], {}).get("cluster_env_str")
            info["results"] = self.bcs_perm_handler(
                request, project_id, info["results"], filter_use=perm_can_use, ns_id_flag="id", ns_name_flag="name"
            )
            if info["results"]:
                ret_data.append(info)
        return APIResponse({
            "data": ret_data
        })
Пример #14
0
    def get(self, request, project_id):
        cluster_type, app_status, tmpl_set_id, app_id, ns_id = self.get_filter_params(request, project_id)
        project_kind = self.project_kind(request)
        # 获取模板集
        all_tmpl_set_list = self.get_filter_tmpl_set(project_id, tmpl_set_id)
        # 获取实例名称
        app_name = self.get_inst_name(app_id)
        # 获取模板
        category = self.get_request_category(request, project_kind)
        tmpl_info, newest_version_tmpl = self.get_template(project_kind, all_tmpl_set_list, category)
        print(app_name, tmpl_info, newest_version_tmpl)

        return APIResponse({"data": {}})
Пример #15
0
    def destroy(self, request, project_id, pk):
        """删除nginx ingress
        1. 标识LB配置
        2. 删除节点标签nodetype
        3. 删除helm记录
        """
        lb_conf = self.get_object()

        perm = bcs_perm.Namespace(request, project_id, lb_conf.namespace_id)
        perm.can_use(raise_exception=True)

        # 标识LB被删除
        self.delete_lb_conf(lb_conf)
        # 删除节点标签
        delete_node_id_list = [
            node_id for node_id in json.loads(lb_conf.ip_info)
        ]
        self.delete_node_label(request, delete_node_id_list, project_id,
                               lb_conf)
        # 删除helm
        app_instance = self.get_k8s_bcs_app(lb_conf.namespace_id,
                                            self.chart_info)
        if not app_instance:
            return APIResponse({"message": _("删除成功")})

        user_log = log_client.ContextActivityLogClient(
            project_id=project_id,
            user=request.user.username,
            resource_type='lb',
            resource="%s:%s" % (lb_conf.cluster_id, lb_conf.namespace_id),
            resource_id=pk)
        app_instance.destroy(username=request.user.username,
                             access_token=request.user.token.access_token)
        # 因为是helm中是异步过程,因此,放到后台处理
        # if App.objects.filter(id=app_instance.id).exists():
        #     user_log.log_delete(activity_status="failed")
        #     return APIResponse({"code": 400, "message": app_instance.transitioning_message})
        user_log.log_delete(activity_status="succeed")
        return APIResponse({"message": _("任务下发成功!")})
Пример #16
0
 def get_namespaces(self, request, project_id):
     """获取namespace
     """
     resp = paas_cc.get_namespace_list(
         request.user.token.access_token,
         project_id, limit=10000, offset=0
     )
     if resp.get("code") != ErrorCode.NoError:
         return False, APIResponse({
             "code": resp.get("code", DEFAULT_ERROR_CODE),
             "message": resp.get("message")
         })
     return True, resp["data"]
Пример #17
0
 def get(self, request, project_id):
     """获取所有实例
     """
     kind = self.project_kind(request)
     cluster_type, category = self.get_cluster_category(request, kind)
     all_musters = self.get_muster(project_id)
     version_inst_map = self.get_version_instances(all_musters.keys())
     version_inst_cluster = self.get_insts(version_inst_map.keys(), category=category)
     cluster_env_map = self.get_cluster_id_env(request, project_id)
     # 组装返回数据
     ret_data = self.compose_data(version_inst_cluster, cluster_env_map, cluster_type)
     ret_data = [{"app_id": val, "app_name": key} for key, val in ret_data.items()]
     return APIResponse({"data": ret_data})
Пример #18
0
    def get_taskgroup(self, request, project_id, lb_id):
        # 判断 lb 的状态
        validate_res, validate_msg = self.validate_lb(request,
                                                      project_id,
                                                      lb_id,
                                                      "get_taskgroup",
                                                      is_check_use=False)
        if not validate_res:
            return Response(validate_msg)

        # 获取kind
        flag, project_kind = self.get_project_kind(request, project_id)
        if not flag:
            return project_kind
        # 根据 lb 获取 Deployment的信息
        name = self.lb_data.get("name")
        cluster_id = self.lb_data.get('cluster_id')
        data_dict = self.lb_data.get('data_dict')
        # 查询 namespace
        if data_dict:
            data_dict = json.loads(data_dict)
        else:
            data_dict = {}
        namespace = get_namespace_name(request.user.token.access_token,
                                       project_id, data_dict)
        # 获取taskagroup或者group
        field = self.get_filed(project_kind)
        rc_names = self.get_rc_name_by_deployment_base(
            request,
            project_id,
            cluster_id,
            name,
            project_kind=project_kind,
            namespace=namespace)
        rc_names = list(set(rc_names)) or ["None"]
        flag, resp = self.get_pod_or_taskgroup(
            request,
            project_id,
            cluster_id,
            field=field,
            app_name=",".join(rc_names),
            ns_name=namespace,
        )
        if not flag:
            return resp
        if project_kind == 2:
            ret_data = self.get_task_group_info_base(resp, namespace=namespace)
        else:
            ret_data = []
        # 处理数据方便前台使用
        return APIResponse({"data": ret_data})
Пример #19
0
    def update_instance(self, request, project_id, cluster_id, ns, instance_num, conf, kind=2, category=None,
                        name=None):  # noqa
        if kind == 2:
            client = MesosClient(
                request.user.token.access_token,
                project_id, cluster_id, None
            )
            resp = client.update_mesos_app_instance(ns, instance_num, conf)
        else:
            client = K8SClient(
                request.user.token.access_token,
                project_id, cluster_id, None
            )
            curr_func = getattr(client, FUNC_MAP[category] % "update")
            resp = curr_func(ns, name, conf)

        if resp.get("code") != ErrorCode.NoError:
            return False, APIResponse({
                "code": resp.get("code", DEFAULT_ERROR_CODE),
                "message": resp.get("message", _("请求出现异常!"))
            })
        return True, APIResponse({
            "message": _("更新成功!")
        })
Пример #20
0
 def get(self, request, project_id):
     """查询项目下不同集群类型的模板集
     """
     flag, kind = self.get_project_kind(request, project_id)
     if not flag:
         return kind
     cluster_type, category = self.get_cluster_category(request, kind)
     all_musters = self.get_muster(project_id)
     version_inst_map = self.get_version_instances(all_musters.keys())
     version_inst_cluster = self.get_insts(version_inst_map.keys(), category=category)
     cluster_env_map = self.get_cluster_id_env(request, project_id)
     # 组装数据
     ret_data = self.compose_data(
         all_musters, version_inst_map, version_inst_cluster, cluster_env_map, cluster_type)
     ret_data = [{"muster_id": key, "muster_name": val} for key, val in ret_data.items()]
     return APIResponse({"data": ret_data})
Пример #21
0
    def get(self, request, project_id):
        """ 获取项目下所有的ConfigMap """
        # 获取kind
        project_kind = request.project.kind
        if project_kind not in [info[0] for info in constants.ProjectKind.get_choices()]:
            raise error_codes.CheckFailed(_("项目编排类型不正确"))

        cluster_dicts = self.get_project_cluster_info(request, project_id)
        cluster_data = cluster_dicts.get('results', {}) or {}

        data = []
        params = dict(request.GET.items())
        s_cate = 'configmap' if project_kind == MESOS_VALUE else 'K8sConfigMap'
        access_token = request.user.token.access_token
        is_decode = request.GET.get('decode')
        is_decode = True if is_decode == '1' else False

        # get project namespace info
        namespace_dict = app_utils.get_ns_id_map(access_token, project_id)

        for cluster_info in cluster_data:
            cluster_id = cluster_info.get('cluster_id')
            # 当参数中集群ID存在时,判断集群ID匹配成功后,继续后续逻辑
            if params.get('cluster_id') and params['cluster_id'] != cluster_id:
                continue
            cluster_env = cluster_info.get('environment')
            code, cluster_configmaps = self.get_configmaps_by_cluster_id(
                request, params, project_id, cluster_id, project_kind=project_kind)
            # 单个集群错误时,不抛出异常信息
            if code != ErrorCode.NoError:
                continue
            self.handle_data(request, cluster_configmaps, project_kind, s_cate,
                             access_token, project_id, cluster_id,
                             is_decode, cluster_env, cluster_info.get('name', ''), namespace_dict=namespace_dict)
            data += cluster_configmaps

        # 按时间倒序排列
        data.sort(key=lambda x: x.get('createTime', ''), reverse=True)

        return APIResponse({
            "code": ErrorCode.NoError,
            "data": {
                "data": data,
                "length": len(data)
            },
            "message": "ok"
        })
Пример #22
0
 def get_mesos_app_deploy_with_post(self,
                                    request,
                                    project_id,
                                    cluster_id,
                                    instance_name=None,
                                    category="application",
                                    field=None,
                                    namespace=None):
     """查询mesos下application和deployment的状态"""
     client = MesosClient(request.user.token.access_token, project_id,
                          cluster_id, None)
     if category == "application":
         resp = retry_requests(
             client.get_application_with_post,
             data={
                 "name": instance_name,
                 "field": field or
                 "data.metadata.name,data.metadata.namespace,data.status,data.message",
                 "namespace": namespace,
             },
         )
     else:
         resp = retry_requests(
             client.get_deployment_with_post,
             data={
                 "name": instance_name,
                 "field": field or
                 "data.metadata.name,data.metadata.namespace,data.status,data.message",
                 "namespace": namespace,
             },
         )
     if resp.get("code") != ErrorCode.NoError:
         return False, APIResponse({
             "code": resp.get("code") or DEFAULT_ERROR_CODE,
             "message": resp.get("message")
         })
     return True, resp
Пример #23
0
 def list(self, request, project_id, cluster_id):
     used_ns_id_list = K8SLoadBlance.objects.filter(
         project_id=project_id, cluster_id=cluster_id,
         is_deleted=False).values("namespace_id")
     return APIResponse(
         {"data": [info["namespace_id"] for info in used_ns_id_list]})
Пример #24
0
    def update(self, request, project_id, pk):
        """
        更新LB配置,包含下面几种场景
        1. 增加/减少LB协议类型
        2. 增加/减少节点数量(标签+replica)
        """
        req_data = dict(request.data)
        req_data.update({"id": pk, "updator": request.user.username})
        serializer = NginxIngressUpdateSLZ(data=req_data)
        serializer.is_valid(raise_exception=True)
        data = serializer.data

        lb_conf, delete_node_id_list, add_node_id_list = self.get_update_node_info(
            request, data)

        perm = bcs_perm.Namespace(request, project_id, lb_conf.namespace_id)
        perm.can_use(raise_exception=True)
        # 判断调整的节点是否已经存在,并且是独享的
        # self.update_check_node_id(lb_conf, data)

        # 删除节点配置
        if delete_node_id_list:
            self.delete_node_label(request, delete_node_id_list, project_id,
                                   lb_conf)
        # 添加节点配置
        if add_node_id_list:
            self.add_node_label(request, add_node_id_list, project_id, lb_conf)

        # 更新lb
        self.update_lb_conf(lb_conf, data["ip_info"], data["protocol_type"],
                            request.user.username)
        app_instance = self.get_k8s_bcs_app(lb_conf.namespace_id,
                                            self.chart_info)
        if not app_instance:
            return APIResponse({"code": 400, "message": _("没有查询到应用信息")})

        data["namespace_id"] = lb_conf.namespace_id
        namespace_info = self.get_ns_info(request, data["namespace_id"])
        valuefile = self.render_yaml(request.user.token.access_token,
                                     project_id, lb_conf.cluster_id, data,
                                     namespace_info)
        user_log = log_client.ContextActivityLogClient(
            project_id=project_id,
            user=request.user.username,
            resource_type='lb',
            resource="%s:%s" % (lb_conf.cluster_id, lb_conf.namespace_id),
            resource_id=pk,
            extra=json.dumps(data))
        updated_instance = app_instance.upgrade_app(
            access_token=request.user.token.access_token,
            chart_version_id=self.chart_version.id,
            answers=[],
            customs=[],
            valuefile=valuefile,
            updator=request.user.username)
        if updated_instance.transitioning_result:
            user_log.log_modify(activity_status="succeed")
            return APIResponse({"message": "更新成功!"})
        user_log.log_modify(activity_status="failed")
        return APIResponse({
            "code": 400,
            "message": updated_instance.transitioning_message
        })
Пример #25
0
    def create(self, request, project_id):
        """针对nginx的实例化,主要有下面几步:
        1. 存储用户设置的配置
        2. 根据用户选择的节点打标签
        3. 根据透露给用户的选择,渲染values.yaml文件
        4. 实例化controller相关配置
        """
        data = dict(request.data)
        data.update({
            "project_id": project_id,
            "creator": request.user.username,
            "updator": request.user.username,
            "name": K8S_LB_NAME
        })
        ns_id = data['namespace_id']
        # 检查命名空间是否被占用
        self.check_namespace_used(data['cluster_id'], ns_id)

        perm = bcs_perm.Namespace(request, project_id, ns_id)
        perm.can_use(raise_exception=True)
        # 检查节点ID是否已经存在,不允许占用独享的节点
        # ip_info = json.loads(data["ip_info"])
        # self.check_used_node(ip_info.keys())

        value_file_content, namespace_info = self.pre_create(request, data)

        user_log = log_client.ContextActivityLogClient(
            project_id=project_id,
            user=request.user.username,
            resource_type='lb',
            resource="%s:%s" % (data["cluster_id"], data["namespace_id"]),
            extra=json.dumps(data))
        # 4. helm apply
        try:
            helm_app_info = App.objects.initialize_app(
                access_token=request.user.token.access_token,
                name=K8S_LB_NAME,
                project_id=project_id,
                cluster_id=data["cluster_id"],
                namespace_id=data["namespace_id"],
                namespace=namespace_info["name"],
                chart_version=self.chart_version,
                answers=[],
                customs=[],
                valuefile=value_file_content,
                creator=request.user.username,
                updator=request.user.username)
        except Exception as err:
            logger.exception('Create helm app error, detail: %s' % err)
            helm_app_info = None
        if helm_app_info:
            if helm_app_info.transitioning_result:
                user_log.log_add(activity_status="succeed")
                return APIResponse({"message": _("创建成功!")})
            else:
                user_log.log_add(activity_status="failed")
                raise error_codes.CheckFailed(_("创建失败,请查看实例详情!"))
        else:
            # 5. 如果失败删除k8s lb实例
            K8SLoadBlance.objects.filter(cluster_id=data["cluster_id"],
                                         namespace_id=data["namespace_id"],
                                         name=data["name"]).delete()

        user_log.log_add(activity_status="failed")
        raise error_codes.CheckFailed(_("创建失败,已通知管理员处理!"))
Пример #26
0
    def get(self, request, project_id):
        """ 获取项目下所有的服务 """
        cluster_dicts = self.get_project_cluster_info(request, project_id)
        cluster_data = cluster_dicts.get('results', {}) or {}

        project_kind = request.project.kind
        params = dict(request.GET.items())
        params['env'] = 'mesos' if project_kind == MESOS_VALUE else 'k8s'

        # 获取命名空间的id
        namespace_dict = app_utils.get_ns_id_map(
            request.user.token.access_token, project_id)

        # 项目下的所有模板集id
        all_template_id_list = Template.objects.filter(
            project_id=project_id,
            edit_mode=TemplateEditMode.PageForm.value).values_list('id',
                                                                   flat=True)
        all_template_id_list = [
            str(template_id) for template_id in all_template_id_list
        ]
        skip_namespace_list = list(K8S_SYS_NAMESPACE)
        skip_namespace_list.extend(K8S_PLAT_NAMESPACE)

        extended_routes = {}
        if project_kind == ProjectKind.K8S.value:
            extended_routes = get_svc_extended_routes(project_id)

        data = []
        for cluster_info in cluster_data:
            cluster_id = cluster_info.get('cluster_id')
            if params.get('cluster_id') and params['cluster_id'] != cluster_id:
                continue
            cluster_name = cluster_info.get('name')
            code, cluster_services = self.get_services_by_cluster_id(
                request,
                params,
                project_id,
                cluster_id,
                project_kind=project_kind)
            if code != ErrorCode.NoError:
                continue
            for _s in cluster_services:
                # NOTE: 兼容处理,因为key: clusterId已被前端使用;通过非bcs创建的service,不一定包含cluster_id
                _s["clusterId"] = cluster_id
                _s["cluster_id"] = cluster_id
                _config = _s.get('data', {})
                annotations = _config.get('metadata',
                                          {}).get('annotations', {})
                _s['update_time'] = annotations.get(ANNOTATIONS_UPDATE_TIME,
                                                    '')
                _s['updator'] = annotations.get(ANNOTATIONS_UPDATOR, '')
                _s['cluster_name'] = cluster_name
                _s['status'] = 'Running'
                _s['environment'] = cluster_info.get('environment')

                _s['can_update'] = True
                _s['can_update_msg'] = ''
                _s['can_delete'] = True
                _s['can_delete_msg'] = ''

                namespace_id = namespace_dict.get(
                    (cluster_id, _s['namespace'])) if namespace_dict else None
                _s['namespace_id'] = namespace_id

                labels = _config.get('metadata', {}).get('labels', {})
                template_id = labels.get(LABLE_TEMPLATE_ID)
                # 资源来源
                source_type = labels.get(SOURCE_TYPE_LABEL_KEY)
                if not source_type:
                    source_type = "template" if template_id else "other"
                _s['source_type'] = SOURCE_TYPE_MAP.get(source_type)

                if project_kind == ProjectKind.K8S.value:
                    _s['access_info'] = get_svc_access_info(
                        _config, _s['clusterId'], extended_routes)
                # 处理 k8s 的系统命名空间的数据
                if project_kind == ProjectKind.K8S.value and _s[
                        'namespace'] in skip_namespace_list:
                    _s['can_update'] = _s['can_delete'] = False
                    _s['can_update_msg'] = _s['can_delete_msg'] = _(
                        "不允许操作系统命名空间")
                    continue

                # 非模板集创建,可以删除但是不可以更新
                _s['can_update'] = False
                _s['can_update_msg'] = _("所属模板集不存在,无法操作")
                if template_id and template_id in all_template_id_list:
                    _s['can_update'] = True
                    _s['can_update_msg'] = ''

            data += cluster_services
        # 按时间倒序排列
        data.sort(key=lambda x: x.get('createTime', ''), reverse=True)

        if data:
            # 检查是否用命名空间的使用权限
            perm = bcs_perm.Namespace(request, project_id, bcs_perm.NO_RES)
            data = perm.hook_perms(data,
                                   ns_id_flag='namespace_id',
                                   cluster_id_flag='clusterId',
                                   ns_name_flag='namespace')
        return APIResponse({
            "code": ErrorCode.NoError,
            "data": {
                "data": data,
                "length": len(data)
            },
            "message": "ok"
        })
Пример #27
0
    def get_service_info(self, request, project_id, cluster_id, namespace,
                         name):  # noqa
        """获取单个 service 的信息"""
        project_kind = request.project.kind
        access_token = request.user.token.access_token
        params = {
            "env": "mesos" if project_kind == MESOS_VALUE else "k8s",
            "namespace": namespace,
            "name": name,
        }
        if project_kind == MESOS_VALUE:
            client = mesos.MesosClient(access_token,
                                       project_id,
                                       cluster_id,
                                       env=None)
            resp = client.get_services(params)
            # 跳转到模板集页面需要的参数
            template_cate = 'mesos'
            relate_app_cate = 'application'
        else:
            client = k8s.K8SClient(access_token,
                                   project_id,
                                   cluster_id,
                                   env=None)
            resp = client.get_service(params)
            template_cate = 'k8s'
            relate_app_cate = 'deployment'

        if resp.get("code") != ErrorCode.NoError:
            raise ComponentError(resp.get("message"))

        resp_data = resp.get("data", [])
        if not resp_data:
            return APIResponse({
                "code":
                400,
                "message":
                _("查询不到 Service[{}] 的信息").format(name)
            })
        s_data = resp_data[0].get('data', {})
        labels = s_data.get('metadata', {}).get('labels') or {}

        # 获取命名空间的id
        namespace_id = app_utils.get_namespace_id(access_token,
                                                  project_id,
                                                  (cluster_id, namespace),
                                                  cluster_id=cluster_id)

        instance_id = labels.get(LABLE_INSTANCE_ID)

        # 是否关联LB
        lb_balance = labels.get('BCSBALANCE')
        if lb_balance:
            s_data['isLinkLoadBalance'] = True
            s_data['metadata']['lb_labels'] = {'BCSBALANCE': lb_balance}
        else:
            s_data['isLinkLoadBalance'] = False
        lb_name = labels.get('BCSGROUP')

        # 获取模板集信息
        template_id = labels.get(LABLE_TEMPLATE_ID)
        try:
            lasetest_ver = ShowVersion.objects.filter(
                template_id=template_id).order_by('-updated').first()
            show_version_name = lasetest_ver.name
            version_id = lasetest_ver.real_version_id
            version_entity = VersionedEntity.objects.get(id=version_id)
        except Exception:
            return APIResponse({
                "code":
                400,
                "message":
                _("模板集[id:{}]没有可用的版本,无法更新service").format(template_id)
            })

        entity = version_entity.get_entity()

        # 获取更新人和创建人
        annotations = s_data.get('metadata', {}).get('annotations', {})
        creator = annotations.get(ANNOTATIONS_CREATOR, '')
        updator = annotations.get(ANNOTATIONS_UPDATOR, '')
        create_time = annotations.get(ANNOTATIONS_CREATE_TIME, '')
        update_time = annotations.get(ANNOTATIONS_UPDATE_TIME, '')

        # k8s 更新需要获取版本号
        resource_version = s_data.get('metadata',
                                      {}).get('resourceVersion') or ''

        web_cache = annotations.get(ANNOTATIONS_WEB_CACHE)
        if not web_cache:
            # 备注中无,则从模板中获取,兼容mesos之前实例化过的模板数据
            _services = entity.get('service') if entity else None
            _services_id_list = _services.split(',') if _services else []
            _s = Service.objects.filter(id__in=_services_id_list,
                                        name=name).first()
            try:
                web_cache = _s.get_config.get('webCache')
            except Exception:
                pass
        else:
            try:
                web_cache = json.loads(web_cache)
            except Exception:
                pass
        s_data['webCache'] = web_cache
        deploy_tag_list = web_cache.get('deploy_tag_list') or []

        app_weight = {}
        if project_kind == MESOS_VALUE:
            # 处理 mesos 中Service的关联数据
            apps = entity.get('application') if entity else None
            application_id_list = apps.split(',') if apps else []

            apps = Application.objects.filter(id__in=application_id_list)
            if apps:
                # 关联应用的权重
                for key in labels:
                    if key.startswith('BCS-WEIGHT-'):
                        app_name = key[11:]
                        _app = apps.filter(name=app_name).first()
                        if _app:
                            weight = int(labels[key])
                            app_weight[_app.app_id] = weight
        else:
            # 处理 k8s 中Service的关联数据
            if not deploy_tag_list:
                _servs = entity.get('K8sService') if entity else None
                _serv_id_list = _servs.split(',') if _servs else []
                _k8s_s = K8sService.objects.filter(id__in=_serv_id_list,
                                                   name=name).first()
                if _k8s_s:
                    deploy_tag_list = _k8s_s.get_deploy_tag_list()

        # 标签 和 备注 去除后台自动添加的
        or_annotations = s_data.get('metadata', {}).get('annotations', {})
        or_labels = s_data.get('metadata', {}).get('labels', {})
        if or_labels:
            pub_keys = PUBLIC_LABELS.keys()
            show_labels = {
                key: or_labels[key]
                for key in or_labels if key not in pub_keys
            }
            s_data['metadata']['labels'] = show_labels
        if or_annotations:
            pub_an_keys = PUBLIC_ANNOTATIONS.keys()
            show_annotations = {
                key: or_annotations[key]
                for key in or_annotations if key not in pub_an_keys
            }
            remove_key(show_annotations, ANNOTATIONS_WEB_CACHE)
            s_data['metadata']['annotations'] = show_annotations

        return APIResponse({
            "data": {
                'service': [{
                    'name': name,
                    'app_id': app_weight.keys(),
                    'app_weight': app_weight,
                    'deploy_tag_list': deploy_tag_list,
                    'config': s_data,
                    'version': version_id,
                    'lb_name': lb_name,
                    'instance_id': instance_id,
                    'namespace_id': namespace_id,
                    'cluster_id': cluster_id,
                    'namespace': namespace,
                    'creator': creator,
                    'updator': updator,
                    'create_time': create_time,
                    'update_time': update_time,
                    'show_version_name': show_version_name,
                    'resource_version': resource_version,
                    'template_id': template_id,
                    'template_cate': template_cate,
                    'relate_app_cate': relate_app_cate,
                }]
            }
        })
Пример #28
0
    def delete_instance(self,
                        request,
                        project_id,
                        cluster_id,
                        ns,
                        instance_name,
                        category="application",
                        kind=2,
                        inst_id_list=None,
                        enforce=0):
        """删除instance
        """
        if kind == 2:
            client = MesosClient(request.user.token.access_token, project_id,
                                 cluster_id, None)
            if category == "application":
                resp = client.delete_mesos_app_instance(ns,
                                                        instance_name,
                                                        enforce=enforce)
            elif category == "deployment":
                resp = client.delete_deployment(ns,
                                                instance_name,
                                                enforce=enforce)
            elif category == "secret":
                resp = client.delete_secret(ns, instance_name)
            elif category == "configmap":
                resp = client.delete_configmap(ns, instance_name)
            else:
                resp = client.delete_service(ns, instance_name)
            if inst_id_list:
                delete_instance_task.delay(request.user.token.access_token,
                                           inst_id_list, kind)
        else:
            client = K8SClient(request.user.token.access_token, project_id,
                               cluster_id, None)
            # deployment 需要级联删除 res\pod; daemonset/job/statefulset 需要级联删除 pod
            if FUNC_MAP[category] in [
                    '%s_deployment', '%s_daemonset', '%s_job', '%s_statefulset'
            ]:
                fun_prefix = 'deep_delete'
            else:
                fun_prefix = 'delete'
            curr_func = getattr(client, FUNC_MAP[category] % fun_prefix)

            resp = curr_func(ns, instance_name)
        # 级联删除,会返回空
        if resp is None:
            # 启动后台任务,轮训任务状态
            if inst_id_list:
                delete_instance_task.delay(request.user.token.access_token,
                                           inst_id_list, kind)
            return APIResponse({
                "code": ErrorCode.NoError,
                "message": _("删除成功")
            })
        curr_msg = resp.get("message")
        if "not found" in curr_msg or "node does not exist" in curr_msg:
            return APIResponse({
                "code": ErrorCode.NoError,
                "message": _("删除成功")
            })
        if resp.get("code") != ErrorCode.NoError:
            return APIResponse({
                "code": resp.get("code") or DEFAULT_ERROR_CODE,
                "message": curr_msg
            })
        return APIResponse({"code": resp.get("code"), "message": curr_msg})
Пример #29
0
    def get(self, request, project_id):
        """ 获取项目下所有的服务 """
        # 获取kind

        logger.debug("get project kind: %s" % project_id)
        project_kind = request.project.kind

        logger.debug("get project clusters: %s" % project_id)
        cluster_dicts = self.get_project_cluster_info(request, project_id)
        cluster_data = cluster_dicts.get('results', {}) or {}

        params = dict(request.GET.items())
        params.update({
            "env": "mesos" if project_kind == MESOS_VALUE else "k8s",
        })

        data = []

        access_token = request.user.token.access_token
        cluster = paas_cc.get_all_clusters(access_token,
                                           project_id,
                                           limit=constants.ALL_LIMIT)
        cluster = cluster.get('data', {}).get('results') or []
        cluster = {i['cluster_id']: i['name'] for i in cluster}

        # 获取命名空间的id
        namespace_dict = app_utils.get_ns_id_map(
            request.user.token.access_token, project_id)

        # 项目下的所有模板集id
        all_template_id_list = Template.objects.filter(
            project_id=project_id).values_list('id', flat=True)
        all_template_id_list = [
            str(template_id) for template_id in all_template_id_list
        ]
        skip_namespace_list = constants.K8S_SYS_NAMESPACE
        skip_namespace_list.extend(constants.K8S_PLAT_NAMESPACE)
        for cluster_info in cluster_data:
            cluster_id = cluster_info.get('cluster_id')
            if params.get('cluster_id') and params['cluster_id'] != cluster_id:
                continue
            cluster_name = cluster_info.get('name')
            code, cluster_services = self.get_services_by_cluster_id(
                request,
                params,
                project_id,
                cluster_id,
                project_kind=project_kind)
            if code != ErrorCode.NoError:
                continue
            for _s in cluster_services:
                _config = _s.get('data', {})
                annotations = _config.get('metadata',
                                          {}).get('annotations', {})
                _s['update_time'] = annotations.get(ANNOTATIONS_UPDATE_TIME,
                                                    '')
                _s['updator'] = annotations.get(ANNOTATIONS_UPDATOR, '')
                _s['cluster_name'] = cluster_name
                _s['status'] = 'Running'
                _s['environment'] = cluster_info.get('environment')

                _s['can_update'] = True
                _s['can_update_msg'] = ''
                _s['can_delete'] = True
                _s['can_delete_msg'] = ''

                namespace_id = namespace_dict.get(
                    (cluster_id, _s['namespace'])) if namespace_dict else None
                _s['namespace_id'] = namespace_id

                labels = _config.get('metadata', {}).get('labels', {})
                template_id = labels.get(LABLE_TEMPLATE_ID)
                # 资源来源
                source_type = labels.get(SOURCE_TYPE_LABEL_KEY)
                if not source_type:
                    source_type = "template" if template_id else "other"
                _s['source_type'] = SOURCE_TYPE_MAP.get(source_type)

                # 处理 k8s 的系统命名空间的数据
                if project_kind == 1 and _s['namespace'] in skip_namespace_list:
                    _s['can_update'] = _s['can_delete'] = False
                    _s['can_update_msg'] = _s['can_delete_msg'] = _(
                        "不允许操作系统命名空间")
                    continue

                # 非模板集创建,可以删除但是不可以更新
                _s['can_update'] = False
                _s['can_update_msg'] = _("所属模板集不存在,无法操作")
                if template_id and template_id in all_template_id_list:
                    _s['can_update'] = True
                    _s['can_update_msg'] = ''

            data += cluster_services
        # 按时间倒序排列
        data.sort(key=lambda x: x.get('createTime', ''), reverse=True)

        if data:
            # 检查是否用命名空间的使用权限
            perm = bcs_perm.Namespace(request, project_id, bcs_perm.NO_RES)
            data = perm.hook_perms(data,
                                   ns_id_flag='namespace_id',
                                   cluster_id_flag='clusterId',
                                   ns_name_flag='namespace')
        return APIResponse({
            "code": ErrorCode.NoError,
            "data": {
                "data": data,
                "length": len(data)
            },
            "message": "ok"
        })
Пример #30
0
    def delete_instance(
        self,
        request,
        project_id,
        cluster_id,
        ns,
        instance_name,
        category="application",
        kind=2,
        inst_id_list=None,
        enforce=0,
    ):
        """删除instance"""
        if kind == 2:
            client = MesosClient(request.user.token.access_token, project_id,
                                 cluster_id, None)
            if category == "application":
                resp = client.delete_mesos_app_instance(ns,
                                                        instance_name,
                                                        enforce=enforce)
            elif category == "deployment":
                resp = client.delete_deployment(ns,
                                                instance_name,
                                                enforce=enforce)
            elif category == "secret":
                resp = client.delete_secret(ns, instance_name)
            elif category == "configmap":
                resp = client.delete_configmap(ns, instance_name)
            else:
                resp = client.delete_service(ns, instance_name)
            if inst_id_list:
                delete_instance_task.delay(request.user.token.access_token,
                                           inst_id_list, kind)
        else:
            client = K8SClient(request.user.token.access_token, project_id,
                               cluster_id, None)
            # deployment 需要级联删除 res\pod; daemonset/job/statefulset 需要级联删除 pod
            if FUNC_MAP[category] in [
                    '%s_deployment', '%s_daemonset', '%s_job', '%s_statefulset'
            ]:
                fun_prefix = 'deep_delete'
            else:
                fun_prefix = 'delete'
            curr_func = getattr(client, FUNC_MAP[category] % fun_prefix)

            resp = curr_func(ns, instance_name)
        # 级联删除,会返回空
        if resp is None:
            # 启动后台任务,轮训任务状态
            if inst_id_list:
                delete_instance_task.delay(request.user.token.access_token,
                                           inst_id_list, kind)
            return APIResponse({
                "code": ErrorCode.NoError,
                "message": _("删除成功")
            })

        # response
        msg = resp.get("message")
        # message中有not found或者node does not exist时,认为已经删除成功
        # 状态码为正常或者满足不存在条件时,认为已经删除成功
        if ((resp.get("code") in [
                ErrorCode.NoError, ErrorCode.MesosDeploymentNotFound,
                ErrorCode.MesosApplicationNotFound
        ]) or ("not found" in msg) or ("node does not exist" in msg)):
            return APIResponse({
                "code": ErrorCode.NoError,
                "message": _("删除成功")
            })

        return APIResponse({"code": resp.get("code"), "message": msg})