Esempio n. 1
0
    def retrieve(self, request, project_id, *args, **kwargs):
        cluster_id = request.query_params.get("cluster_id")

        check_cluster_perm(user=request.user,
                           project_id=project_id,
                           cluster_id=cluster_id,
                           request=request)

        # 获取镜像地址
        jfrog_domain = paas_cc.get_jfrog_domain(access_token=self.access_token,
                                                project_id=self.project_id,
                                                cluster_id=cluster_id)

        cluster_info = paas_cc.get_cluster(request.user.token.access_token,
                                           project_id, cluster_id)["data"]

        context = dict(
            cluster_id=cluster_id,
            cluster_name=cluster_info["name"],
            jfrog_domain=jfrog_domain,
            expr="{{ .Values.__BCS__.SYS_JFROG_DOMAIN }}",
            link=settings.HELM_DOC_TRICKS,
        )
        note = _('''集群: {cluster}({cluster_id})的容器仓库域名为:{dept_domain},
        可在Chart直接引用 {expr} 更加方便, [详细说明]({link})''').format(
            cluster=context['cluster_name'],
            cluster_id=context['cluster_id'],
            dept_domain=context['jfrog_domain'],
            expr=context['expr'],
            link=context['link'],
        )
        context["note"] = note
        return Response(data=context)
Esempio n. 2
0
    def create(self, request, project_id, *args, **kwargs):
        serializer = ClusterImportSLZ(data=request.data)
        serializer.is_valid(raise_exception=True)

        cluster_id = serializer.data["cluster_id"]

        check_cluster_perm(user=request.user,
                           project_id=project_id,
                           cluster_id=cluster_id,
                           request=request)

        bcs_client = bcs_utils_client.get_bcs_client(
            project_id=project_id,
            cluster_id=cluster_id,
            access_token=self.access_token)
        bcs_cluster_info = bcs_client.get_or_register_bcs_cluster()
        if not bcs_cluster_info["result"]:
            return Response(data=bcs_cluster_info)

        bcs_cluster_info = bcs_cluster_info["data"]
        content = render_bcs_agent_template(
            token=bcs_cluster_info["token"],
            bcs_cluster_id=bcs_cluster_info["bcs_cluster_id"],
            namespace=self.bcs_agent_namespace,
            access_token=self.access_token,
            project_id=project_id,
            cluster_id=cluster_id,
        )

        response = HttpResponse(content=content,
                                content_type='text/plain; charset=UTF-8')
        response[
            'Content-Disposition'] = 'attachment; filename="bcs-agent-%s.yaml"' % cluster_id
        return response
Esempio n. 3
0
    def create(self, validated_data):
        namespace_info = self.get_ns_info_by_id(validated_data["namespace_info"])

        check_cluster_perm(
            user=self.context["request"].user,
            project_id=namespace_info["project_id"],
            cluster_id=namespace_info["cluster_id"],
            request=self.context["request"],
        )

        sys_variables = collect_system_variable(
            access_token=self.context["request"].user.token.access_token,
            project_id=namespace_info["project_id"],
            namespace_id=namespace_info["id"],
        )

        return App.objects.initialize_app(
            access_token=self.access_token,
            name=validated_data.get("name"),
            project_id=self.project_id,
            cluster_id=namespace_info["cluster_id"],
            namespace_id=namespace_info["id"],
            namespace=namespace_info["name"],
            chart_version=validated_data["chart_version"],
            answers=validated_data["get_answers"],
            customs=validated_data["get_customs"],
            valuefile=validated_data.get("get_valuefile"),
            creator=self.request_username,
            updator=self.request_username,
            sys_variables=sys_variables,
            valuefile_name=validated_data.get('get_valuefile_name'),
            cmd_flags=validated_data["cmd_flags"],
        )
Esempio n. 4
0
    def create(self, validated_data):
        data = super(AppCreatePreviewDiffWithClusterSLZ,
                     self).create(validated_data)
        namespace_info = self.get_ns_info_by_id(
            validated_data["namespace_info"])

        check_cluster_perm(
            user=self.context["request"].user,
            project_id=namespace_info["project_id"],
            cluster_id=namespace_info["cluster_id"],
            request=self.context["request"],
        )

        with save_to_temporary_dir(data["content"]) as tempdir:
            with make_kubectl_client(
                    project_id=self.project_id,
                    cluster_id=namespace_info["cluster_id"],
                    access_token=self.access_token) as (client, err):
                if err:
                    raise serializers.ValidationError(
                        "make kubectl client failed, %s", err)

                args = [
                    "kubediff", "--kubeconfig", client.kubeconfig, "--json",
                    "--no-error-on-diff", tempdir
                ]
                difference = subprocess.check_output(args)
                difference = json.loads(difference)
                data.update(difference=difference)

        return data
Esempio n. 5
0
    def provide(user, config):
        from backend.helm.app.models import App
        from backend.utils.client import get_kubectl_config_context

        if not App.objects.filter(project_id=config.get("project_id"),
                                  cluster_id=config.get("cluster_id"),
                                  id=config.get("app_id")).exists():
            raise PermissionDenied()

        check_cluster_perm(user, config.get("project_id"),
                           config.get("cluster_id"))

        # bke_client = get_bke_client(
        #     project_id=config.get("project_id"),
        #     cluster_id=config.get("cluster_id"),
        #     access_token=user.token.access_token
        # )
        # bke_client.active_admin()

        kubeconfig = get_kubectl_config_context(
            access_token=user.token.access_token,
            project_id=config.get("project_id"),
            cluster_id=config.get("cluster_id"),
        )
        kubeconfig_obj = yaml_load(kubeconfig)
        kubeconfig_obj["users"][0]["user"]["token"] = settings.BKE_ADMIN_TOKEN
        config["kubeconfig"] = yaml_dump(kubeconfig_obj)
        return config
Esempio n. 6
0
    def update(self, request, project_id, app_id, *args, **kwargs):
        app = self.queryset.get(project_id=project_id, id=app_id)

        check_cluster_perm(user=request.user,
                           project_id=app.project_id,
                           cluster_id=app.cluster_id,
                           request=request)

        app.inject_configs = None
        app.save(update_fields=["inject_configs"])
        return Response(data={"code": 0, "message": "ok"})
Esempio n. 7
0
    def update(self, instance, validated_data):
        check_cluster_perm(
            user=self.context["request"].user,
            project_id=instance.project_id,
            cluster_id=instance.cluster_id,
            request=self.context["request"],
        )

        # operation record
        return instance.rollback_app(
            username=self.request_username,
            access_token=self.access_token,
            release_id=validated_data["release"],
        )
Esempio n. 8
0
    def create(self, validated_data):
        """ 生成应用的预览数据 """
        instance = App.objects.get(id=self.app_id)

        check_cluster_perm(
            user=self.context["request"].user,
            project_id=instance.project_id,
            cluster_id=instance.cluster_id,
            request=self.context["request"],
        )

        difference = instance.diff_release(release_id=validated_data["release"])
        content, notes = instance.render_app(
            username=self.context["request"].user.username, access_token=self.access_token
        )
        return {
            "difference": difference,
            "content": preview_parse(content, instance.namespace),
            "notes": notes,
        }
Esempio n. 9
0
    def create(self, request, project_id, *args, **kwargs):
        serializer = ClusterKubeConfigSLZ(data=request.data)
        serializer.is_valid(raise_exception=True)

        cluster_id = serializer.data["cluster_id"]

        check_cluster_perm(user=request.user,
                           project_id=project_id,
                           cluster_id=cluster_id,
                           request=request)

        kubeconfig = bcs_utils_client.get_kubectl_config_context(
            access_token=self.access_token,
            project_id=project_id,
            cluster_id=cluster_id)

        response = HttpResponse(content=kubeconfig,
                                content_type='text/plain; charset=UTF-8')
        response[
            'Content-Disposition'] = 'attachment; filename="bcs-%s-kubeconfig.yaml"' % cluster_id
        return response
Esempio n. 10
0
    def retrieve(self, request, app_id, *args, **kwargs):
        app = App.objects.get(id=self.app_id)

        check_cluster_perm(user=request.user,
                           project_id=app.project_id,
                           cluster_id=app.cluster_id,
                           request=request)

        content = app.release.content
        # resources = parser.parse(content, app.namespace)
        with bcs_utils_client.make_kubectl_client(
                access_token=self.access_token,
                project_id=app.project_id,
                cluster_id=app.cluster_id) as (client, err):
            if err:
                raise APIException(str(err))

            state = collect_resource_state(kube_client=client,
                                           namespace=app.namespace,
                                           content=content)

        return Response(state)
Esempio n. 11
0
    def create(self, request, project_id, *args, **kwargs):
        serializer = ClusterKubeConfigSLZ(data=request.data)
        serializer.is_valid(raise_exception=True)

        cluster_id = serializer.data["cluster_id"]

        check_cluster_perm(user=request.user,
                           project_id=project_id,
                           cluster_id=cluster_id,
                           request=request)

        # 检查是否有 node, 没有node时,bcs-agent无法启动
        nodes_info = paas_cc.get_node_list(self.access_token, project_id,
                                           cluster_id)
        if not nodes_info["data"]["results"]:
            return Response(data={
                "code": 40032,
                "message": _("集群下没有Node节点,无法启用,请先添加")
            })
        data = helm_init(self.access_token, project_id, cluster_id,
                         self.bcs_agent_namespace)

        return Response(data=data)
Esempio n. 12
0
    def destroy(self, request, *args, **kwargs):
        """重载默认的 destroy 方法,用于实现判断是否删除成功"""
        instance = self.get_object()

        check_cluster_perm(user=request.user,
                           project_id=instance.project_id,
                           cluster_id=instance.cluster_id,
                           request=request)

        self.perform_destroy(instance)

        if App.objects.filter(id=instance.id).exists():
            instance = App.objects.get(id=instance.id)
            data = {
                "transitioning_result": instance.transitioning_result,
                "transitioning_message": instance.transitioning_message,
            }
        else:
            data = {
                "transitioning_result": True,
                "transitioning_message": "success deleted"
            }
        return Response(data)
Esempio n. 13
0
    def retrieve(self, request, project_id, *args, **kwargs):
        parameter = dict(request.GET.items())
        serializer = ClusterKubeConfigSLZ(data=parameter)
        serializer.is_valid(raise_exception=True)

        cluster_id = serializer.data["cluster_id"]

        check_cluster_perm(user=request.user,
                           project_id=project_id,
                           cluster_id=cluster_id,
                           request=request)

        if settings.HELM_HAS_ABILITY_SUPPLY_CHART_REPO_SERVICE:
            bcs_client = bcs_utils_client.get_bcs_client(
                project_id=project_id,
                cluster_id=cluster_id,
                access_token=self.access_token)

            bcs_cluster_info = bcs_client.get_cluster()
            if bcs_cluster_info is None or not bcs_cluster_info.get(
                    "bcs_cluster_id"):
                result = {
                    "code": 17602,
                    "message": "cluster does not regist to bcs yet.",
                    "initialized": False
                }
                return Response(result)

        serializer = self.serializer_class({
            "public_repos":
            self.get_or_add_public_repos(project_id),
            "private_repos":
            self.get_or_add_private_repos(project_id, request.user),
            "initialized":
            True,
        })
        return Response(data=serializer.data)
Esempio n. 14
0
    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)

        # 获取dashboard对应的path
        bin_path = get_helm_dashboard_path(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,
                                               bin_path=bin_path)
        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)
Esempio n. 15
0
    def create(self, validated_data):
        """ 生成应用的预览数据,这个时候应用没有创建,release也没有创建 """
        namespace_info = self.get_ns_info_by_id(validated_data["namespace_info"])

        cluster_id = namespace_info["cluster_id"]
        check_cluster_perm(
            user=self.context["request"].user,
            project_id=namespace_info["project_id"],
            cluster_id=cluster_id,
            request=self.context["request"],
        )

        # prepare parameters
        parameters = merge_rancher_answers(validated_data["get_answers"], validated_data["get_customs"])

        valuefile = get_valuefile_with_bcs_variable_injected(
            access_token=self.context["request"].user.token.access_token,
            project_id=namespace_info["project_id"],
            namespace_id=namespace_info["id"],
            valuefile=validated_data["valuefile"],
            cluster_id=cluster_id,
        )

        # inject bcs info
        now = datetime.datetime.now()
        username = self.context["request"].user.username

        # 组装注入的参数
        bcs_inject_data = bcs_helm_utils.BCSInjectData(
            source_type="helm",
            creator=username,
            updator=username,
            version=validated_data["chart_version"].version,
            project_id=self.project_id,
            app_id=self.context["request"].project.cc_app_id,
            cluster_id=cluster_id,
            namespace=namespace_info["name"],
            stdlog_data_id=bcs_helm_utils.get_stdlog_data_id(self.project_id),
            image_pull_secret=bcs_helm_utils.provide_image_pull_secrets(namespace_info["name"]),
        )
        client = KubeHelmClient(helm_bin=settings.HELM3_BIN)
        try:
            extra_params = {"cmd_flags": validated_data["cmd_flags"]}
            content, notes = client.template_with_ytt_renderer(
                files=validated_data["chart_version"].files,
                namespace=namespace_info["name"],
                name=validated_data.get("name"),
                parameters=parameters,
                valuefile=valuefile,
                cluster_id=cluster_id,
                bcs_inject_data=bcs_inject_data,
                **extra_params
            )
        except helm_exceptions.HelmBaseException:
            # raise ParseError(str(e))
            # NOTE: 现阶段为防止出现未测试到的情况,允许出错时,按照先前流程渲染;后续删除
            content, notes = _template_with_bcs_renderer(
                client,
                validated_data["chart_version"].files,
                validated_data.get("name"),
                namespace_info["name"],
                namespace_info["id"],
                parameters,
                valuefile,
                cluster_id,
                username,
                now,
                validated_data["chart_version"].version,
                self.access_token,
                self.project_id,
            )

        return {"content": preview_parse(content, namespace_info["name"]), "notes": notes}
Esempio n. 16
0
    def create(self, validated_data):
        """ 应用更新时的预览数据,这个时候目标release还没有创建 """
        instance = App.objects.get(id=self.app_id)

        check_cluster_perm(
            user=self.context["request"].user,
            project_id=instance.project_id,
            cluster_id=instance.cluster_id,
            request=self.context["request"],
        )

        # 标记Chart中的values.yaml是否发生变化,用于提醒用户
        chart_version_changed = False

        # prepare parameters
        parameters = merge_rancher_answers(validated_data["get_answers"], validated_data["get_customs"])

        chart_version_id = validated_data["upgrade_verion"]
        chart_version_id = int(chart_version_id)
        if chart_version_id == KEEP_TEMPLATE_UNCHANGED:
            files = instance.release.chartVersionSnapshot.files
        else:
            chart_version_changed = True
            chart_version = ChartVersion.objects.get(id=chart_version_id)
            files = chart_version.files

        valuefile = get_valuefile_with_bcs_variable_injected(
            access_token=self.context["request"].user.token.access_token,
            project_id=instance.project_id,
            namespace_id=instance.namespace_id,
            valuefile=validated_data["valuefile"],
            cluster_id=instance.cluster_id,
        )

        now = datetime.datetime.now()
        username = self.context["request"].user.username
        # 组装注入的参数
        bcs_inject_data = bcs_helm_utils.BCSInjectData(
            source_type="helm",
            creator=username,
            updator=username,
            version=instance.release.chartVersionSnapshot.version,
            project_id=self.project_id,
            app_id=self.context["request"].project.cc_app_id,
            cluster_id=instance.cluster_id,
            namespace=instance.namespace,
            stdlog_data_id=bcs_helm_utils.get_stdlog_data_id(self.project_id),
            image_pull_secret=bcs_helm_utils.provide_image_pull_secrets(instance.namespace),
        )
        # 默认为使用helm3 client
        client = KubeHelmClient(helm_bin=settings.HELM3_BIN)
        try:
            content, notes = client.template_with_ytt_renderer(
                files=files,
                namespace=instance.namespace,
                name=instance.name,
                parameters=parameters,
                valuefile=valuefile,
                cluster_id=instance.cluster_id,
                bcs_inject_data=bcs_inject_data,
            )
        except helm_exceptions.HelmBaseException:
            # raise ParseError(str(e))
            # NOTE: 现阶段为防止出现未测试到的情况,允许出错时,按照先前流程渲染;后续删除
            content, notes = _template_with_bcs_renderer(
                client,
                files,
                instance.name,
                instance.namespace,
                instance.namespace_id,
                parameters,
                valuefile,
                instance.cluster_id,
                username,
                now,
                instance.release.chartVersionSnapshot.version,
                self.access_token,
                instance.project_id,
            )

        # compute diff
        old_content = instance.release.content
        if not old_content:
            old_content, _ = instance.render_app(
                username=self.context["request"].user.username, access_token=self.access_token
            )
        difference = simple_diff(old_content, content, instance.namespace)
        return {
            "content": preview_parse(content, instance.namespace),
            "notes": notes,
            "difference": difference,
            "chart_version_changed": chart_version_changed,
            "old_content": old_content,
            "new_content": content,
        }