Full Code of caoyingjunz/gopixiu for AI

master 5fd5f7d45c3f cached
158 files
746.1 KB
266.4k tokens
1054 symbols
1 requests
Download .txt
Showing preview only (806K chars total). Download the full file or copy to clipboard to get everything.
Repository: caoyingjunz/gopixiu
Branch: master
Commit: 5fd5f7d45c3f
Files: 158
Total size: 746.1 KB

Directory structure:
gitextract__nbx67ym/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── build-webshell-image.yml
│       ├── ci.yml
│       └── docker-image.yml
├── .gitignore
├── Makefile
├── README.md
├── api/
│   ├── docs/
│   │   ├── docs.go
│   │   ├── swagger.json
│   │   └── swagger.yaml
│   └── server/
│       ├── errors/
│       │   └── errors.go
│       ├── httpstatus/
│       │   └── status.go
│       ├── httputils/
│       │   ├── docs.go
│       │   ├── httputils.go
│       │   └── httputils_test.go
│       ├── middleware/
│       │   ├── admission.go
│       │   ├── audit.go
│       │   ├── authentication.go
│       │   ├── authorization.go
│       │   ├── cors.go
│       │   ├── limiter.go
│       │   ├── log.go
│       │   └── middleware.go
│       ├── router/
│       │   ├── audit/
│       │   │   ├── audit.go
│       │   │   └── audit_routes.go
│       │   ├── auth/
│       │   │   ├── auth.go
│       │   │   └── auth_routes.go
│       │   ├── cluster/
│       │   │   ├── cluster.go
│       │   │   ├── cluster_routes.go
│       │   │   ├── helper.go
│       │   │   ├── informer.go
│       │   │   ├── proxy.go
│       │   │   └── ws.go
│       │   ├── helm/
│       │   │   ├── helm.go
│       │   │   ├── release_routes.go
│       │   │   └── respository_routes.go
│       │   ├── plan/
│       │   │   ├── config_routes.go
│       │   │   ├── node_routes.go
│       │   │   ├── plan.go
│       │   │   ├── plan_routes.go
│       │   │   └── task_routes.go
│       │   ├── proxy/
│       │   │   ├── helper.go
│       │   │   └── proxy.go
│       │   ├── router.go
│       │   ├── static/
│       │   │   └── index.html
│       │   ├── tenant/
│       │   │   ├── tenant.go
│       │   │   └── tenant_routes.go
│       │   └── user/
│       │       ├── user.go
│       │       └── user_routes.go
│       └── validator/
│           ├── helper.go
│           ├── password.go
│           ├── rbac.go
│           └── validator.go
├── cmd/
│   ├── app/
│   │   ├── config/
│   │   │   └── config.go
│   │   ├── options/
│   │   │   └── options.go
│   │   └── server.go
│   └── pixiuserver.go
├── config.yaml
├── deploy/
│   ├── README.md
│   └── pixiu/
│       ├── .helmignore
│       ├── Chart.yaml
│       ├── templates/
│       │   ├── NOTES.txt
│       │   ├── _helpers.tpl
│       │   ├── configmap.yaml
│       │   ├── deployment.yaml
│       │   ├── hpa.yaml
│       │   ├── ingress.yaml
│       │   ├── service.yaml
│       │   └── serviceaccount.yaml
│       └── values.yaml
├── docker/
│   ├── Dockerfile
│   ├── Dockerfile-toolbox
│   └── start.sh
├── docs/
│   ├── OWNERS
│   ├── README.md
│   ├── apis.md
│   └── sql.md
├── go.mod
├── go.sum
├── hack/
│   ├── tools/
│   │   └── licfmt/
│   │       └── licfmt.go
│   ├── update-gofmt.sh
│   ├── update-image.sh
│   └── verify-gofmt.sh
├── install.md
├── pkg/
│   ├── client/
│   │   ├── cache.go
│   │   ├── client.go
│   │   ├── helm.go
│   │   ├── task.go
│   │   ├── token_cache.go
│   │   └── user_cache.go
│   ├── controller/
│   │   ├── audit/
│   │   │   └── audit.go
│   │   ├── auth/
│   │   │   └── auth.go
│   │   ├── cluster/
│   │   │   ├── cluster.go
│   │   │   ├── informer.go
│   │   │   ├── util.go
│   │   │   └── ws.go
│   │   ├── controller.go
│   │   ├── helm/
│   │   │   ├── helm.go
│   │   │   ├── releases.go
│   │   │   └── repository.go
│   │   ├── plan/
│   │   │   ├── bootstrap_servers.go
│   │   │   ├── checker.go
│   │   │   ├── deploy.go
│   │   │   ├── plan.go
│   │   │   ├── plan_config.go
│   │   │   ├── plan_node.go
│   │   │   ├── plan_task.go
│   │   │   ├── register.go
│   │   │   ├── render.go
│   │   │   └── worker.go
│   │   ├── tenant/
│   │   │   └── tenant.go
│   │   ├── user/
│   │   │   ├── user.go
│   │   │   └── user_test.go
│   │   └── util/
│   │       └── util.go
│   ├── db/
│   │   ├── audit.go
│   │   ├── cluster.go
│   │   ├── factory.go
│   │   ├── logger.go
│   │   ├── migrator.go
│   │   ├── model/
│   │   │   ├── audit.go
│   │   │   ├── cluster.go
│   │   │   ├── model.go
│   │   │   ├── pixiu/
│   │   │   │   └── model.go
│   │   │   ├── plan.go
│   │   │   ├── rbac.go
│   │   │   ├── rbac_test.go
│   │   │   ├── repository.go
│   │   │   ├── tenant.go
│   │   │   └── user.go
│   │   ├── options.go
│   │   ├── plan.go
│   │   ├── repository.go
│   │   ├── tenant.go
│   │   └── user.go
│   ├── jobmanager/
│   │   ├── audit_cleaner.go
│   │   ├── cluster_syncer.go
│   │   ├── context.go
│   │   └── manager.go
│   ├── static/
│   │   ├── localfile.go
│   │   └── static.go
│   ├── types/
│   │   ├── helm.go
│   │   ├── meta.go
│   │   ├── request.go
│   │   └── types.go
│   └── util/
│       ├── container/
│       │   └── container.go
│       ├── errors/
│       │   └── errors.go
│       ├── log/
│       │   └── log.go
│       ├── lru/
│       │   └── lru.go
│       ├── ssh/
│       │   └── ssh.go
│       ├── token/
│       │   └── token.go
│       ├── util.go
│       ├── util_test.go
│       └── uuid/
│           └── uuid.go
└── template/
    ├── globals.go
    ├── hosts.go
    └── multinode.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
labels: ["kind/bug"]
about: Create a report to help us improve
---

**Describe the Bug**
A clear and concise description of what the bug is.

For UI issues please also add a screenshot that shows the issue.

**Versions Used**
KubeSphere:
Kubernetes: (If KubeSphere installer used, you can skip this)

**Environment**
How many nodes and their hardware configuration:

For example: CentOS 7.5 / 3 masters:  8cpu/8g; 3 nodes: 8cpu/16g
(and other info are welcomed to help us debugging)

**How To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature Request
about: Have a good idea? Please don't hesitate to write it down, describe the new feature.
---

**What's it about?**
<!--
A clear and concise description of what this feature request is.
-->

**What's the reason why we need it?**
<!--
Please tell us if you think it's a necessary feature for Pixiu. Give us as many details about it as you can.
Two or more use cases might be very helpful when other contributors try to go through this request. If you have some references,
please just add it below.
-->

I believe this is an important feature for Pixiu. There're a few use cases:

* case one
* case two
* ...

Please leave your comments below if there's anyone agrees with me. Or just give me a thumb up.

**Area Suggestion**
<!--
In order to have a clear issue list, giving an accuracy area is necessary. If you are not sure about it, please just leave it alone.

You can find some possible areas below. Please attention, sometimes crossing multiple areas might be possible. So, you
can keep one or more areas in this issue.

> /area alerting
> /area api
> /area apiserver
> /area app-management
> /area audit
> /area console
> /area devops
> /area documentation
> /area edge
> /area iam
> /area installation
> /area logging
> /area microservice
> /area monitoring
> /area multicluster
> /area networking
> /area notification
> /area observability
> /area performance
> /area security
> /area storage
> /area test
> /area upgrade
-->

/kind feature-request


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
#### What type of PR is this?

<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature
/kind design

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

#### What this PR does / why we need it:

#### Which issue(s) this PR fixes:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #

#### Special notes for your reviewer:

#### Does this PR introduce a user-facing change?
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->
```release-note

```

#### Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

<!--
This section can be blank if this pull request does not require a release note.

When adding links which point to resources within git repositories, like
KEPs or supporting documentation, please reference a specific commit and avoid
linking directly to the master branch. This ensures that links reference a
specific point in time, rather than a document that may change over time.

See here for guidance on getting permanent links to files: https://help.github.com/en/articles/getting-permanent-links-to-files

Please use the following format for linking documentation:
- [KEP]: <link>
- [Usage]: <link>
- [Other doc]: <link>
-->
```docs

```


================================================
FILE: .github/workflows/build-webshell-image.yml
================================================
name: Publish webshell image

on:
  push:
    branches:
      - "master"
    paths:
      - 'docker/Dockerfile-toolbox'
      - 'Makefile'

env:
  K8S_VERSION: v1.23.6 # the same as Makefile
  HELM_VERSION: v3.7.1 # the same as Makefile

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Get short commit hash
        run: echo "COMMIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login in dockerhub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_NAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and push webshell image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./docker/Dockerfile-toolbox
          platforms: linux/amd64,linux/arm64
          build-args: |
            K8S_VERSION=${{ env.K8S_VERSION }}
            HELM_VERSION=${{ env.HELM_VERSION }}
          push: true
          tags: |
            ${{ secrets.DOCKER_NAME }}/pixiu-webshell:latest
            ${{ secrets.DOCKER_NAME }}/pixiu-webshell:v0.1
            ${{ secrets.DOCKER_NAME }}/pixiu-webshell:${{ env.COMMIT_HASH }}


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

env:
  GO_VERSION: '1.17.5'

jobs:
#  markdown-lint:
#    runs-on: ubuntu-latest
#    container: node:14
#    steps:
#      - name: Checkout
#        uses: actions/checkout@v4
#
#      - name: Install mdl
#        run: apt update && apt-get install ruby-full -y && gem install chef-utils -v 16.6.14 && gem install mdl -v 0.11.0
#
#      - name: Lint markdown files
#        run: find  ./ -name  "*.md" | grep -v '.github' | xargs mdl -r ~MD001,~MD004,~MD005,~MD006,~MD007,~MD010,~MD013,~MD022,~MD023,~MD024,~MD025,~MD029,~MD031,~MD032,~MD033,~MD034,~MD036

  golang-lint:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
      with:
        submodules: true

    - name: Set up Golang
      uses: actions/setup-go@v2
      with:
        go-version: ${{ env.GO_VERSION }}

    - name: Run go fmt test
      run: hack/verify-gofmt.sh
      env:
        GO111MODULE: auto

    - name: Build the pixiu binariy
      run: go build -v ./...

    - name: Run pixiu unit test
      run: go test -v ./...


================================================
FILE: .github/workflows/docker-image.yml
================================================
name: Publish pixiu image

on:
  push:
    branches:
      - "master"
    paths-ignore:
      - 'docs/**'

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Get short commit hash
        run: |
          echo "COMMIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
          echo "TIMESTAMP=$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      # - name: Login harbor
      #   uses: docker/login-action@v3
      #   with:
      #     registry: crpi-0ecikjs9ylb2hqyo.cn-hangzhou.personal.cr.aliyuncs.com
      #     username: ${{ secrets.HARBOR_USERNAME }}
      #     password: ${{ secrets.HARBOR_PASSWORD }}

      # - name: Build and push the pixiu image
      #   uses: docker/build-push-action@v5
      #   with:
      #     context: .
      #     file: ./docker/Dockerfile
      #     platforms: linux/amd64,linux/arm64
      #     build-args: |
      #       VERSION=${{ env.COMMIT_HASH }}-${{ env.TIMESTAMP }}
      #     push: true
      #     tags: |
      #       crpi-0ecikjs9ylb2hqyo.cn-hangzhou.personal.cr.aliyuncs.com/pixiu-public/pixiu:latest
      #       crpi-0ecikjs9ylb2hqyo.cn-hangzhou.personal.cr.aliyuncs.com/pixiu-public/pixiu:v1.0.1
      #       crpi-0ecikjs9ylb2hqyo.cn-hangzhou.personal.cr.aliyuncs.com/pixiu-public/pixiu:${{ env.COMMIT_HASH }}


================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin
testbin/*

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Kubernetes Generated files - skip generated files, except for vendored files
!vendor/**/zz_generated.*

# editor and IDE paraphernalia
.idea
.vscode
.gitcommits
*.swp
*.swo

# output
dist

# licensefmt
hack/tools/licfmt/licfmt

vendor


================================================
FILE: Makefile
================================================
.PHONY: run build image push clean

tag = v0.1
releaseName = pixiu
dockerhubUser ?= jacky06
k8sVersion ?= v1.23.6
helmVersion ?= v3.7.1
targetDir ?= dist
commitHash = $(shell git rev-parse --short HEAD)
# e.g. 1862ce5-20240203180617
version = $(commitHash)-$(shell date +%Y%m%d%H%M%S)

ALL: run

run: build
	./pixiu --configfile ./config.yaml

build:
	go build -o $(targetDir)/$(releaseName) -ldflags "-X 'main.version=$(version)'" ./cmd/

image:
	docker build -t $(dockerhubUser)/$(releaseName):$(tag) --build-arg VERSION=$(version) .

push: image
	docker push $(dockerhubUser)/$(releaseName):$(tag)

webshell-image:
	docker build --build-arg K8S_VERSION=$(k8sVersion) \
		--build-arg HELM_VERSION=$(helmVersion) \
		-t $(dockerhubUser)/pixiu-webshell:$(tag) -f docker/Dockerfile .

push-webshell-image: webshell-image
	docker push $(dockerhubUser)/pixiu-webshell:$(tag)

licfmt:
	go run hack/tools/licfmt/licfmt.go -v ./*

clean:
	-rm -f ./$(releaseName)

.PHONY: api-docs
api-docs: ## generate the api docs
	swag init --generalInfo ./cmd/pixiuserver.go --output ./api/docs


================================================
FILE: README.md
================================================
# Pixiu Overview

Pixiu is an open source container platform for cloud-native application management.

![Build Status][build-url]
[![Release][release-image]][release-url]
[![License][license-image]][license-url]

## 安装手册
- [安装手册](install.md)

## 页面展示
### 首页
<img width="1647" alt="image" src="https://github.com/youdian-xiaoshuai/pixiu/assets/64686398/9fc5e005-95cd-49ee-a13c-13f22949fd74">

### 部署计划
- 创建部署计划
    ```text
    通过新建部署计划,可以实现通过页面 `点点点` 的方式创建 `kubernetes` 集群, 如同各大云厂商一样
    ```
    ![image](https://github.com/pixiu-io/dashboard/blob/master/images/plan_deploy.png?raw=true)

- 新建节点
    ```text
    1. 添加各个节点的信息,节点的角色,用户名,密码等
    2. 各大组件支持高度的自定义,例如:calico,fannel
    2. kubernetes 版本自主选择
    ```
    ![image](https://github.com/pixiu-io/dashboard/blob/master/images/plan_node.png?raw=true)

- 部署详情
    ```text
    可以看到部署计划在每个部署的运行状态,以及详细日志
    ```
    ![image](https://github.com/pixiu-io/dashboard/blob/master/images/plan_detail.png?raw=true)

### 集群管理
- 集群概览
    ```text
    cpu状态,内存状态,集群的基本信息,网络信息,集群服务
    ```
    ![image](https://github.com/pixiu-io/dashboard/blob/master/images/cluster_detail.png?raw=true)

- 集群管理
![image](https://github.com/pixiu-io/dashboard/blob/master/images/cluster_manager.png?raw=true)

- 集群工作负载deployment
![image](https://github.com/pixiu-io/dashboard/blob/master/images/cluster_deploy.png?raw=true)

- 集群工作负载pod
![image](https://github.com/pixiu-io/dashboard/blob/master/images/cluster_pod.png?raw=true)

### 审计功能
- 审计管理
![image](https://github.com/pixiu-io/dashboard/blob/master/images/audit_manager.png?raw=true)

## 学习分享
- [go-learning](https://github.com/caoyingjunz/go-learning)

## 沟通交流
- 搜索微信号 `yingjuncz`, 备注(pixiu), 验证通过会加入群聊
- [bilibili](https://space.bilibili.com/3493104248162809?spm_id_from=333.1007.0.0) 技术分享

Copyright 2019 caoyingjun (cao.yingjunz@gmail.com) Apache License 2.0

[build-url]: https://github.com/caoyingjunz/pixiu/actions/workflows/ci.yml/badge.svg
[release-image]: https://img.shields.io/badge/release-download-orange.svg
[release-url]: https://www.apache.org/licenses/LICENSE-2.0.html
[license-image]: https://img.shields.io/badge/license-Apache%202-4EB1BA.svg
[license-url]: https://www.apache.org/licenses/LICENSE-2.0.html


================================================
FILE: api/docs/docs.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package docs GENERATED BY SWAG; DO NOT EDIT
// This file was generated by swaggo/swag
package docs

import "github.com/swaggo/swag"

const docTemplate = `{
    "schemes": {{ marshal .Schemes }},
    "swagger": "2.0",
    "info": {
        "description": "{{escape .Description}}",
        "title": "{{.Title}}",
        "termsOfService": "https://github.com/caoyingjunz/pixiu",
        "contact": {
            "name": "API Support",
            "url": "https://github.com/caoyingjunz/pixiu",
            "email": "support@pixiu.io"
        },
        "license": {
            "name": "Apache 2.0",
            "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
        },
        "version": "{{.Version}}"
    },
    "host": "{{.Host}}",
    "basePath": "{{.BasePath}}",
    "paths": {
        "/pixiu/clusters": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "List clusters",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "List clusters",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "array",
                            "items": {
                                "allOf": [
                                    {
                                        "$ref": "#/definitions/httputils.Response"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "result": {
                                                "type": "array",
                                                "items": {
                                                    "$ref": "#/definitions/types.Cluster"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/clusters/": {
            "post": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Create by a json cluster",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Create a cluster",
                "parameters": [
                    {
                        "description": "Create cluster",
                        "name": "cluster",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.Cluster"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/clusters/{clusterId}": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Get by cloud cluster ID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Get Cluster by clusterId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/httputils.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "result": {
                                            "$ref": "#/definitions/types.Cluster"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "put": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Update by json cluster",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Update an cluster",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Update cluster",
                        "name": "cluster",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.Cluster"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Delete by cloud cluster ID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Delete cluster by clusterId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/clusters/{clusterId}/ping": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Do ping",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Ping cluster",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "array",
                            "items": {
                                "$ref": "#/definitions/httputils.Response"
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "List users",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "List users",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "array",
                            "items": {
                                "allOf": [
                                    {
                                        "$ref": "#/definitions/httputils.Response"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "result": {
                                                "type": "array",
                                                "items": {
                                                    "$ref": "#/definitions/types.User"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users/": {
            "post": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Create by a json user",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Create a user",
                "parameters": [
                    {
                        "description": "Create user",
                        "name": "user",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.User"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users/login": {
            "post": {
                "description": "Login by a json user",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Login"
                ],
                "summary": "User login",
                "parameters": [
                    {
                        "description": "User login",
                        "name": "user",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.User"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users/{userId}": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Get by user ID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Get user by userId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "userId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/httputils.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "result": {
                                            "$ref": "#/definitions/types.User"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "put": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Update by json user",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Update an user",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "userId",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Update user",
                        "name": "user",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.User"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Delete by userID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Delete user by userId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "userId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "httputils.Response": {
            "type": "object",
            "properties": {
                "code": {
                    "description": "返回的状态码",
                    "type": "integer"
                },
                "message": {
                    "description": "异常返回时的错误信息",
                    "type": "string"
                },
                "result": {
                    "description": "正常返回时的数据,可以为任意数据结构"
                }
            }
        },
        "types.Cluster": {
            "type": "object",
            "properties": {
                "alias_name": {
                    "type": "string"
                },
                "cluster_type": {
                    "description": "0:标准集群 1: 自建集群",
                    "type": "integer"
                },
                "description": {
                    "description": "集群用途描述,可以为空",
                    "type": "string"
                },
                "gmt_create": {
                    "description": "pixiu 对象创建时间",
                    "type": "string"
                },
                "gmt_modified": {
                    "description": "pixiu 对象修改时间",
                    "type": "string"
                },
                "id": {
                    "description": "pixiu 对象 ID",
                    "type": "integer"
                },
                "kube_config": {
                    "description": "k8s kubeConfig base64 字段",
                    "type": "string"
                },
                "kubernetes_version": {
                    "description": "集群的版本",
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "nodes": {
                    "description": "节点数量",
                    "type": "integer"
                },
                "resource_version": {
                    "description": "Pixiu 对象版本号",
                    "type": "integer"
                },
                "resources": {
                    "description": "The memory and cpu usage",
                    "$ref": "#/definitions/types.Resources"
                }
            }
        },
        "types.Resources": {
            "type": "object",
            "properties": {
                "cpu": {
                    "type": "string"
                },
                "memory": {
                    "type": "string"
                }
            }
        },
        "types.User": {
            "type": "object",
            "properties": {
                "description": {
                    "description": "用户描述信息",
                    "type": "string"
                },
                "email": {
                    "description": "用户注册邮件",
                    "type": "string"
                },
                "gmt_create": {
                    "description": "pixiu 对象创建时间",
                    "type": "string"
                },
                "gmt_modified": {
                    "description": "pixiu 对象修改时间",
                    "type": "string"
                },
                "id": {
                    "description": "pixiu 对象 ID",
                    "type": "integer"
                },
                "name": {
                    "description": "用户名称",
                    "type": "string"
                },
                "password": {
                    "description": "用户密码",
                    "type": "string"
                },
                "resource_version": {
                    "description": "Pixiu 对象版本号",
                    "type": "integer"
                },
                "role": {
                    "description": "用户角色,目前只实现管理员,0: 普通用户 1: 管理员 2: 超级管理员",
                    "type": "string"
                },
                "status": {
                    "description": "用户状态标识",
                    "type": "integer"
                }
            }
        }
    },
    "securityDefinitions": {
        "Bearer": {
            "description": "Type \"Bearer\" followed by a space and JWT token",
            "type": "apiKey",
            "name": "Authorization",
            "in": "header"
        }
    }
}`

// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
	Version:          "1.0",
	Host:             "localhost:8090",
	BasePath:         "",
	Schemes:          []string{"http", "https"},
	Title:            "Pixiu API Documentation",
	Description:      "",
	InfoInstanceName: "swagger",
	SwaggerTemplate:  docTemplate,
}

func init() {
	swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}


================================================
FILE: api/docs/swagger.json
================================================
{
    "schemes": [
        "http",
        "https"
    ],
    "swagger": "2.0",
    "info": {
        "title": "Pixiu API Documentation",
        "termsOfService": "https://github.com/caoyingjunz/pixiu",
        "contact": {
            "name": "API Support",
            "url": "https://github.com/caoyingjunz/pixiu",
            "email": "support@pixiu.io"
        },
        "license": {
            "name": "Apache 2.0",
            "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
        },
        "version": "1.0"
    },
    "host": "localhost:8090",
    "paths": {
        "/pixiu/clusters": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "List clusters",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "List clusters",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "array",
                            "items": {
                                "allOf": [
                                    {
                                        "$ref": "#/definitions/httputils.Response"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "result": {
                                                "type": "array",
                                                "items": {
                                                    "$ref": "#/definitions/types.Cluster"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/clusters/": {
            "post": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Create by a json cluster",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Create a cluster",
                "parameters": [
                    {
                        "description": "Create cluster",
                        "name": "cluster",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.Cluster"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/clusters/{clusterId}": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Get by cloud cluster ID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Get Cluster by clusterId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/httputils.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "result": {
                                            "$ref": "#/definitions/types.Cluster"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "put": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Update by json cluster",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Update an cluster",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Update cluster",
                        "name": "cluster",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.Cluster"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Delete by cloud cluster ID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Delete cluster by clusterId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/clusters/{clusterId}/ping": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Do ping",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Clusters"
                ],
                "summary": "Ping cluster",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Cluster ID",
                        "name": "clusterId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "array",
                            "items": {
                                "$ref": "#/definitions/httputils.Response"
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "List users",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "List users",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "array",
                            "items": {
                                "allOf": [
                                    {
                                        "$ref": "#/definitions/httputils.Response"
                                    },
                                    {
                                        "type": "object",
                                        "properties": {
                                            "result": {
                                                "type": "array",
                                                "items": {
                                                    "$ref": "#/definitions/types.User"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users/": {
            "post": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Create by a json user",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Create a user",
                "parameters": [
                    {
                        "description": "Create user",
                        "name": "user",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.User"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users/login": {
            "post": {
                "description": "Login by a json user",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Login"
                ],
                "summary": "User login",
                "parameters": [
                    {
                        "description": "User login",
                        "name": "user",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.User"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        },
        "/pixiu/users/{userId}": {
            "get": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Get by user ID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Get user by userId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "userId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/httputils.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "result": {
                                            "$ref": "#/definitions/types.User"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "put": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Update by json user",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Update an user",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "userId",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Update user",
                        "name": "user",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/types.User"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "description": "Delete by userID",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Users"
                ],
                "summary": "Delete user by userId",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "userId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/httputils.Response"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "httputils.Response": {
            "type": "object",
            "properties": {
                "code": {
                    "description": "返回的状态码",
                    "type": "integer"
                },
                "message": {
                    "description": "异常返回时的错误信息",
                    "type": "string"
                },
                "result": {
                    "description": "正常返回时的数据,可以为任意数据结构"
                }
            }
        },
        "types.Cluster": {
            "type": "object",
            "properties": {
                "alias_name": {
                    "type": "string"
                },
                "cluster_type": {
                    "description": "0:标准集群 1: 自建集群",
                    "type": "integer"
                },
                "description": {
                    "description": "集群用途描述,可以为空",
                    "type": "string"
                },
                "gmt_create": {
                    "description": "pixiu 对象创建时间",
                    "type": "string"
                },
                "gmt_modified": {
                    "description": "pixiu 对象修改时间",
                    "type": "string"
                },
                "id": {
                    "description": "pixiu 对象 ID",
                    "type": "integer"
                },
                "kube_config": {
                    "description": "k8s kubeConfig base64 字段",
                    "type": "string"
                },
                "kubernetes_version": {
                    "description": "集群的版本",
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "nodes": {
                    "description": "节点数量",
                    "type": "integer"
                },
                "resource_version": {
                    "description": "Pixiu 对象版本号",
                    "type": "integer"
                },
                "resources": {
                    "description": "The memory and cpu usage",
                    "$ref": "#/definitions/types.Resources"
                }
            }
        },
        "types.Resources": {
            "type": "object",
            "properties": {
                "cpu": {
                    "type": "string"
                },
                "memory": {
                    "type": "string"
                }
            }
        },
        "types.User": {
            "type": "object",
            "properties": {
                "description": {
                    "description": "用户描述信息",
                    "type": "string"
                },
                "email": {
                    "description": "用户注册邮件",
                    "type": "string"
                },
                "gmt_create": {
                    "description": "pixiu 对象创建时间",
                    "type": "string"
                },
                "gmt_modified": {
                    "description": "pixiu 对象修改时间",
                    "type": "string"
                },
                "id": {
                    "description": "pixiu 对象 ID",
                    "type": "integer"
                },
                "name": {
                    "description": "用户名称",
                    "type": "string"
                },
                "password": {
                    "description": "用户密码",
                    "type": "string"
                },
                "resource_version": {
                    "description": "Pixiu 对象版本号",
                    "type": "integer"
                },
                "role": {
                    "description": "用户角色,目前只实现管理员,0: 普通用户 1: 管理员 2: 超级管理员",
                    "type": "string"
                },
                "status": {
                    "description": "用户状态标识",
                    "type": "integer"
                }
            }
        }
    },
    "securityDefinitions": {
        "Bearer": {
            "description": "Type \"Bearer\" followed by a space and JWT token",
            "type": "apiKey",
            "name": "Authorization",
            "in": "header"
        }
    }
}

================================================
FILE: api/docs/swagger.yaml
================================================
definitions:
  httputils.Response:
    properties:
      code:
        description: 返回的状态码
        type: integer
      message:
        description: 异常返回时的错误信息
        type: string
      result:
        description: 正常返回时的数据,可以为任意数据结构
    type: object
  types.Cluster:
    properties:
      alias_name:
        type: string
      cluster_type:
        description: '0:标准集群 1: 自建集群'
        type: integer
      description:
        description: 集群用途描述,可以为空
        type: string
      gmt_create:
        description: pixiu 对象创建时间
        type: string
      gmt_modified:
        description: pixiu 对象修改时间
        type: string
      id:
        description: pixiu 对象 ID
        type: integer
      kube_config:
        description: k8s kubeConfig base64 字段
        type: string
      kubernetes_version:
        description: 集群的版本
        type: string
      name:
        type: string
      nodes:
        description: 节点数量
        type: integer
      resource_version:
        description: Pixiu 对象版本号
        type: integer
      resources:
        $ref: '#/definitions/types.Resources'
        description: The memory and cpu usage
    type: object
  types.Resources:
    properties:
      cpu:
        type: string
      memory:
        type: string
    type: object
  types.User:
    properties:
      description:
        description: 用户描述信息
        type: string
      email:
        description: 用户注册邮件
        type: string
      gmt_create:
        description: pixiu 对象创建时间
        type: string
      gmt_modified:
        description: pixiu 对象修改时间
        type: string
      id:
        description: pixiu 对象 ID
        type: integer
      name:
        description: 用户名称
        type: string
      password:
        description: 用户密码
        type: string
      resource_version:
        description: Pixiu 对象版本号
        type: integer
      role:
        description: '用户角色,目前只实现管理员,0: 普通用户 1: 管理员 2: 超级管理员'
        type: string
      status:
        description: 用户状态标识
        type: integer
    type: object
host: localhost:8090
info:
  contact:
    email: support@pixiu.io
    name: API Support
    url: https://github.com/caoyingjunz/pixiu
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  termsOfService: https://github.com/caoyingjunz/pixiu
  title: Pixiu API Documentation
  version: "1.0"
paths:
  /pixiu/clusters:
    get:
      consumes:
      - application/json
      description: List clusters
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            items:
              allOf:
              - $ref: '#/definitions/httputils.Response'
              - properties:
                  result:
                    items:
                      $ref: '#/definitions/types.Cluster'
                    type: array
                type: object
            type: array
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: List clusters
      tags:
      - Clusters
  /pixiu/clusters/:
    post:
      consumes:
      - application/json
      description: Create by a json cluster
      parameters:
      - description: Create cluster
        in: body
        name: cluster
        required: true
        schema:
          $ref: '#/definitions/types.Cluster'
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/httputils.Response'
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Create a cluster
      tags:
      - Clusters
  /pixiu/clusters/{clusterId}:
    delete:
      consumes:
      - application/json
      description: Delete by cloud cluster ID
      parameters:
      - description: Cluster ID
        in: path
        name: clusterId
        required: true
        type: integer
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/httputils.Response'
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Delete cluster by clusterId
      tags:
      - Clusters
    get:
      consumes:
      - application/json
      description: Get by cloud cluster ID
      parameters:
      - description: Cluster ID
        in: path
        name: clusterId
        required: true
        type: integer
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            allOf:
            - $ref: '#/definitions/httputils.Response'
            - properties:
                result:
                  $ref: '#/definitions/types.Cluster'
              type: object
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Get Cluster by clusterId
      tags:
      - Clusters
    put:
      consumes:
      - application/json
      description: Update by json cluster
      parameters:
      - description: Cluster ID
        in: path
        name: clusterId
        required: true
        type: integer
      - description: Update cluster
        in: body
        name: cluster
        required: true
        schema:
          $ref: '#/definitions/types.Cluster'
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/httputils.Response'
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Update an cluster
      tags:
      - Clusters
  /pixiu/clusters/{clusterId}/ping:
    get:
      consumes:
      - application/json
      description: Do ping
      parameters:
      - description: Cluster ID
        in: path
        name: clusterId
        required: true
        type: integer
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            items:
              $ref: '#/definitions/httputils.Response'
            type: array
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Ping cluster
      tags:
      - Clusters
  /pixiu/users:
    get:
      consumes:
      - application/json
      description: List users
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            items:
              allOf:
              - $ref: '#/definitions/httputils.Response'
              - properties:
                  result:
                    items:
                      $ref: '#/definitions/types.User'
                    type: array
                type: object
            type: array
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: List users
      tags:
      - Users
  /pixiu/users/:
    post:
      consumes:
      - application/json
      description: Create by a json user
      parameters:
      - description: Create user
        in: body
        name: user
        required: true
        schema:
          $ref: '#/definitions/types.User'
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/httputils.Response'
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Create a user
      tags:
      - Users
  /pixiu/users/{userId}:
    delete:
      consumes:
      - application/json
      description: Delete by userID
      parameters:
      - description: User ID
        in: path
        name: userId
        required: true
        type: integer
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/httputils.Response'
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Delete user by userId
      tags:
      - Users
    get:
      consumes:
      - application/json
      description: Get by user ID
      parameters:
      - description: User ID
        in: path
        name: userId
        required: true
        type: integer
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            allOf:
            - $ref: '#/definitions/httputils.Response'
            - properties:
                result:
                  $ref: '#/definitions/types.User'
              type: object
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Get user by userId
      tags:
      - Users
    put:
      consumes:
      - application/json
      description: Update by json user
      parameters:
      - description: User ID
        in: path
        name: userId
        required: true
        type: integer
      - description: Update user
        in: body
        name: user
        required: true
        schema:
          $ref: '#/definitions/types.User'
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/httputils.Response'
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      security:
      - Bearer: []
      summary: Update an user
      tags:
      - Users
  /pixiu/users/login:
    post:
      consumes:
      - application/json
      description: Login by a json user
      parameters:
      - description: User login
        in: body
        name: user
        required: true
        schema:
          $ref: '#/definitions/types.User'
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/httputils.Response'
        "400":
          description: Bad Request
          schema:
            $ref: '#/definitions/httputils.Response'
        "404":
          description: Not Found
          schema:
            $ref: '#/definitions/httputils.Response'
        "500":
          description: Internal Server Error
          schema:
            $ref: '#/definitions/httputils.Response'
      summary: User login
      tags:
      - Login
schemes:
- http
- https
securityDefinitions:
  Bearer:
    description: Type "Bearer" followed by a space and JWT token
    in: header
    name: Authorization
    type: apiKey
swagger: "2.0"


================================================
FILE: api/server/errors/errors.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package errors

import (
	"net/http"

	"github.com/caoyingjunz/pixiu/pkg/util/errors"
)

type Error struct {
	Code int
	Err  error
}

func (e Error) Error() string {
	return e.Err.Error()
}

func NewError(err error, code int) Error {
	return Error{
		Code: code,
		Err:  err,
	}
}

var (
	ErrUnauthorized = Error{
		Code: http.StatusUnauthorized,
		Err:  errors.NoUserIdError,
	}
	ErrForbidden = Error{
		Code: http.StatusForbidden,
		Err:  errors.NoPermission,
	}
	ErrInvalidRequest = Error{
		Code: http.StatusBadRequest,
		Err:  errors.ErrReqParams,
	}
	ErrServerInternal = Error{
		Code: http.StatusInternalServerError,
		Err:  errors.ErrInternal,
	}
	ErrUserNotFound = Error{
		Code: http.StatusNotFound,
		Err:  errors.ErrUserNotFound,
	}
	ErrNotAcceptable = Error{
		Code: http.StatusNotAcceptable,
		Err:  errors.ErrNotAcceptable,
	}
	ErrUserExists = Error{
		Code: http.StatusConflict,
		Err:  errors.UserExistError,
	}
	ErrInvalidPassword = Error{
		Code: http.StatusUnauthorized,
		Err:  errors.ErrUserPassword,
	}
	ErrDuplicatedPassword = Error{
		Code: http.StatusConflict,
		Err:  errors.ErrDuplicatedPassword,
	}
	ErrClusterNotFound = Error{
		Code: http.StatusNotFound,
		Err:  errors.ErrClusterNotFound,
	}
	ErrTenantExists = Error{
		Code: http.StatusConflict,
		Err:  errors.TenantExistError,
	}
	ErrTenantNotFound = Error{
		Code: http.StatusNotFound,
		Err:  errors.ErrTenantNotFound,
	}
	ErrAuditNotFound = Error{
		Code: http.StatusNotFound,
		Err:  errors.ErrAuditNotFound,
	}
	ErrAuditExists = Error{
		Code: http.StatusConflict,
		Err:  errors.ErrAuditExists,
	}
	ErrRBACPolicyExists = Error{
		Code: http.StatusConflict,
		Err:  errors.PolicyExistError,
	}
	ErrRBACPolicyNotFound = Error{
		Code: http.StatusNotFound,
		Err:  errors.PolicyNotExistError,
	}
	ErrGroupBindingExists = Error{
		Code: http.StatusConflict,
		Err:  errors.PolicyExistError,
	}
	ErrGroupBindingNotFound = Error{
		Code: http.StatusNotFound,
		Err:  errors.PolicyNotExistError,
	}
	ErrRootAlreadyExists = Error{
		Code: http.StatusConflict,
		Err:  errors.ErrRootAlreadyExists,
	}
)


================================================
FILE: api/server/httpstatus/status.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package httpstatus

// TODO: 自定义状态码


================================================
FILE: api/server/httputils/docs.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package httputils

// HttpOK 正常返回
type HttpOK struct {
	Code   int    `json:"code" example:"200"`
	Result string `json:"result" example:"any result"`
}

// HttpError 异常返回
type HttpError struct {
	Code    int    `json:"code" example:"400"`
	Message string `json:"message" example:"status bad request"`
}


================================================
FILE: api/server/httputils/httputils.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package httputils

import (
	"context"
	goerrors "errors"
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"

	"github.com/caoyingjunz/pixiu/api/server/errors"
	validatorutil "github.com/caoyingjunz/pixiu/api/server/validator"
	"github.com/caoyingjunz/pixiu/pkg/db/model"
)

type Response struct {
	Code    int         `json:"code"`              // 返回的状态码
	Result  interface{} `json:"result,omitempty"`  // 正常返回时的数据,可以为任意数据结构
	Message string      `json:"message,omitempty"` // 异常返回时的错误信息
}

func (r *Response) SetCode(c int) {
	r.Code = c
}

func (r *Response) SetMessage(m interface{}) {
	switch msg := m.(type) {
	case error:
		r.Message = msg.Error()
	case string:
		r.Message = msg
	}
}

func (r *Response) SetMessageWithCode(m interface{}, c int) {
	r.SetCode(c)
	r.SetMessage(m)
}

func (r *Response) Error() string {
	return r.Message
}

func (r *Response) String() string {
	//data, _ := json.Marshal(r)
	//return string(data)
	return ""
}

// NewResponse 构造 http 返回值
// SetSuccess 时设置 code 为 200 并追加 success 的标识
// SetFailed 时设置 code 为 400,也可以自定义设置错误码,并追加报错信息
func NewResponse() *Response {
	return &Response{}
}

// SetSuccess 设置成功返回值
func SetSuccess(c *gin.Context, r *Response) {
	_ = contextBind(c).withResponseCode(http.StatusOK)
	r.SetMessageWithCode("success", http.StatusOK)
	c.JSON(http.StatusOK, r)
}

// SetFailed 设置错误返回值
func SetFailed(c *gin.Context, r *Response, err error) {
	switch e := err.(type) {
	case errors.Error:
		setFailedWithCode(c, r, e.Code, e)
	case validator.ValidationErrors:
		setFailedWithValidationError(c, r, validatorutil.TranslateError(e))
	default:
		setFailedWithCode(c, r, http.StatusBadRequest, err)
	}
}

// SetFailedWithCode 设置错误返回值
func setFailedWithCode(c *gin.Context, r *Response, code int, err error) {
	_ = contextBind(c).withResponseCode(code).withRawError(err)
	r.SetMessageWithCode(err, code)
	c.JSON(http.StatusOK, r)
}

func setFailedWithValidationError(c *gin.Context, r *Response, e string) {
	_ = contextBind(c).withResponseCode(http.StatusBadRequest).withRawError(goerrors.New(e))
	r.SetMessageWithCode(e, http.StatusBadRequest)
	c.JSON(http.StatusOK, r)
}

// AbortFailedWithCode 设置错误,code 返回值并终止请求
func AbortFailedWithCode(c *gin.Context, code int, err error) {
	r := NewResponse()
	_ = contextBind(c).withResponseCode(code).withRawError(err)
	r.SetMessageWithCode(err, code)
	c.JSON(http.StatusOK, r)
	c.Abort()
}

func ShouldBindAny(c *gin.Context, jsonObject interface{}, uriObject interface{}, queryObject interface{}) error {
	var err error
	if jsonObject != nil {
		if err = c.ShouldBindJSON(jsonObject); err != nil {
			return err
		}
	}
	if uriObject != nil {
		if err = c.ShouldBindUri(uriObject); err != nil {
			return err
		}
	}
	if queryObject != nil {
		if err = c.ShouldBindQuery(queryObject); err != nil {
			return err
		}
	}
	return nil
}

const userKey = "user"

func GetUserFromRequest(ctx context.Context) (*model.User, error) {
	val := ctx.Value(userKey)
	if val == nil {
		return nil, fmt.Errorf("get nil user")
	}

	user, ok := val.(*model.User)
	if !ok {
		return nil, fmt.Errorf("failed to assert user")
	}
	return user, nil
}

func GetUserIdFromContext(ctx context.Context) (int64, error) {
	user, err := GetUserFromRequest(ctx)
	if err != nil {
		return 0, err
	}
	return user.Id, nil
}

func SetUserToContext(c *gin.Context, user *model.User) {
	c.Set(userKey, user)
}

func GetObjectFromRequest(c *gin.Context) (string, string, bool) {
	return getObjectFromRequest(c.Request.URL.Path)
}

// getObjectFromRequest cuts and returns the object from the request path.
// e.g. /pixiu/clusters/1 -> "clusters" "1" true
func getObjectFromRequest(path string) (obj, sid string, ok bool) {
	// must start with /
	l := len(path)
	if l == 0 || path[0] != '/' {
		return
	}
	subs := strings.Split(path[1:l], "/")
	l = len(subs)
	if l < 2 || subs[0] != "pixiu" {
		return
	}
	if l == 2 {
		// e.g. /pixiu/clusters -> "clusters" "" true
		return subs[1], "", subs[1] != ""
	}
	return subs[1], subs[2], subs[1] != "" && subs[2] != ""
}

const (
	objIDsKey = "objIDs"
)

func SetIdRangeContext(c *gin.Context, ids []int64) {
	c.Set(objIDsKey, ids)
}

func GetIdRangeFromListReq(ctx context.Context) (exists bool, ids []int64) {
	val := ctx.Value(objIDsKey)
	if val == nil {
		return
	}

	ids, exists = val.([]int64)
	return
}

const (
	ResponseCodeKey = "response_code"
	RawErrorKey     = "raw_error"
)

type ctxBind struct {
	*gin.Context
}

func contextBind(c *gin.Context) *ctxBind {
	return &ctxBind{c}
}

// withResponseCode puts the response code into the HTTP context.
func (cb *ctxBind) withResponseCode(code int) *ctxBind {
	cb.Set(ResponseCodeKey, code)
	return cb
}

// withRawError puts the raw error into the HTTP context.
func (cb *ctxBind) withRawError(err error) *ctxBind {
	cb.Set(RawErrorKey, err)
	return cb
}

// GetResponseCode gets the response code from the HTTP context.
func GetResponseCode(ctx context.Context) (code int) {
	val := ctx.Value(ResponseCodeKey)
	if val == nil {
		return
	}

	code = val.(int)
	return
}

// GetRawError gets the raw error from the HTTP context.
func GetRawError(ctx context.Context) (err error) {
	val := ctx.Value(RawErrorKey)
	if val == nil {
		return
	}

	err = val.(error)
	return
}


================================================
FILE: api/server/httputils/httputils_test.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package httputils

import "testing"

func Test_getObjectFromRequest(t *testing.T) {
	tests := []struct {
		name    string
		path    string
		wantObj string
		wantSid string
		wantOk  bool
	}{
		{
			name:    "test0",
			path:    "",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test1",
			path:    "/",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test2",
			path:    "//",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test3",
			path:    "pixiu",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test4",
			path:    "/pixiu",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test5",
			path:    "/pixiu/",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test6",
			path:    "/pixiu/users",
			wantObj: "users",
			wantSid: "",
			wantOk:  true,
		},
		{
			name:    "test7",
			path:    "/pixiu/users/",
			wantObj: "users",
			wantOk:  false,
		},
		{
			name:    "test8",
			path:    "/pixiu/users/1",
			wantObj: "users",
			wantSid: "1",
			wantOk:  true,
		},
		{
			name:    "test9",
			path:    "/pixiu//",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test10",
			path:    "///",
			wantObj: "",
			wantOk:  false,
		},
		{
			name:    "test11",
			path:    "/pixiu/users/1/password",
			wantObj: "users",
			wantSid: "1",
			wantOk:  true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			gotObj, gotSid, gotOk := getObjectFromRequest(tt.path)
			if gotObj != tt.wantObj {
				t.Errorf("getObjectFromRequest() gotObj = %v, want %v", gotObj, tt.wantObj)
			}
			if gotSid != tt.wantSid {
				t.Errorf("getObjectFromRequest() gotSid = %v, want %v", gotSid, tt.wantSid)
			}
			if gotOk != tt.wantOk {
				t.Errorf("getObjectFromRequest() gotOk = %v, want %v", gotOk, tt.wantOk)
			}
		})
	}
}


================================================
FILE: api/server/middleware/admission.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import "github.com/gin-gonic/gin"

// Admission 准入控制
func Admission() gin.HandlerFunc {
	return func(c *gin.Context) {}
}


================================================
FILE: api/server/middleware/audit.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import (
	"context"
	"net/http"
	"strings"
	"sync"
	"time"

	"github.com/gin-contrib/requestid"
	"github.com/gin-gonic/gin"
	"k8s.io/klog/v2"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/db"
	"github.com/caoyingjunz/pixiu/pkg/db/model"
)

const (
	defaultAuditQueueSize = 2048
	defaultAuditWorkers   = 2
	auditWriteTimeout     = 3 * time.Second
)

type auditRecorder struct {
	factory db.ShareDaoFactory
	queue   chan *model.Audit
}

var (
	recorderOnce sync.Once
	recorderInst *auditRecorder
)

func getAuditRecorder(o *options.Options) *auditRecorder {
	recorderOnce.Do(func() {
		recorderInst = &auditRecorder{
			factory: o.Factory,
			queue:   make(chan *model.Audit, defaultAuditQueueSize),
		}
		for i := 0; i < defaultAuditWorkers; i++ {
			go recorderInst.run()
		}
	})
	return recorderInst
}

func (r *auditRecorder) run() {
	for record := range r.queue {
		r.write(record)
	}
}

func (r *auditRecorder) write(record *model.Audit) {
	ctx, cancel := context.WithTimeout(context.Background(), auditWriteTimeout)
	defer cancel()

	if _, err := r.factory.Audit().Create(ctx, record); err != nil {
		klog.Errorf("failed to create audit record [%s]: %v", record.String(), err)
	}
}

func (r *auditRecorder) enqueue(record *model.Audit) {
	select {
	case r.queue <- record:
	default:
		// 队列满时降级同步写入,确保非 GET 请求都能落库
		klog.Warningf("audit queue is full, fallback to direct write: %s", record.Path)
		r.write(record)
	}
}

func Audit(o *options.Options) gin.HandlerFunc {
	recorder := getAuditRecorder(o)
	return func(c *gin.Context) {
		if !shouldAudit(c) {
			c.Next()
			return
		}

		startTime := time.Now()
		c.Next()
		recorder.enqueue(buildAuditRecord(c, startTime))
	}
}

func buildAuditRecord(c *gin.Context, startTime time.Time) *model.Audit {
	userName := "unknown"
	if user, err := httputils.GetUserFromRequest(c); err == nil && user != nil {
		userName = user.Name
	}

	cluster, resourceName, resourceNamespace := parseK8sProxyPath(c.Request.URL.Path)

	return &model.Audit{
		RequestId:         requestid.Get(c),
		Action:            c.Request.Method,
		Ip:                c.ClientIP(),
		Operator:          userName,
		Path:              c.Request.RequestURI,
		ObjectType:        detectObjectType(c),
		Status:            getAuditStatus(c),
		Duration:          time.Since(startTime).Milliseconds(),
		ResponseCode:      c.Writer.Status(),
		Cluster:           cluster,
		ResourceName:      resourceName,
		ResourceNamespace: resourceNamespace,
	}
}

// parseK8sProxyPath 从 K8s proxy URL 路径中解析集群、资源名称和命名空间。
// 支持以下路径格式:
//   - /pixiu/proxy/{cluster}/api/v1/namespaces/{namespace}/{resource}/{name}
//   - /pixiu/proxy/{cluster}/apis/{group}/{version}/namespaces/{namespace}/{resource}/{name}
//   - /pixiu/proxy/{cluster}/api/v1/{resource}/{name}(集群级资源)
func parseK8sProxyPath(path string) (cluster, resourceName, resourceNamespace string) {
	// /pixiu/proxy/{cluster}/...
	const proxyPrefix = "/pixiu/proxy/"
	if !strings.HasPrefix(path, proxyPrefix) {
		return
	}

	rest := path[len(proxyPrefix):]
	parts := strings.SplitN(rest, "/", 2)
	if len(parts) < 1 || parts[0] == "" {
		return
	}
	cluster = parts[0]
	if len(parts) < 2 {
		return
	}

	segments := strings.Split(parts[1], "/")
	// 查找 namespaces/{ns} 段
	for i := 0; i < len(segments)-1; i++ {
		if segments[i] == "namespaces" {
			resourceNamespace = segments[i+1]
			// namespace 之后还有 {resource}/{name}
			if i+3 < len(segments) {
				resourceName = segments[i+3]
			}
			return
		}
	}
	// 无 namespaces 段,集群级资源:api/v1/{resource}/{name} 或 apis/.../.../{resource}/{name}
	if len(segments) > 0 {
		resourceName = segments[len(segments)-1]
	}
	return
}

func shouldAudit(c *gin.Context) bool {
	if c.Request.Method == http.MethodGet || c.Request.Method == http.MethodOptions {
		return false
	}
	return strings.HasPrefix(c.Request.URL.Path, "/pixiu")
}

func detectObjectType(c *gin.Context) model.ObjectType {
	obj, _, ok := httputils.GetObjectFromRequest(c)
	if !ok {
		return model.ObjectAll
	}
	ot := model.ObjectType(obj)
	if _, exists := model.ObjectTypeMap[ot]; exists {
		return ot
	}
	return model.ObjectAll
}

// getAuditStatus returns the status of operation.
func getAuditStatus(c *gin.Context) model.AuditOperationStatus {
	respCode := httputils.GetResponseCode(c)
	if respCode == 0 {
		respCode = c.Writer.Status()
		if respCode == 0 {
			return model.AuditOpUnknown
		}
	}

	if responseOK(respCode) {
		return model.AuditOpSuccess
	}

	return model.AuditOpFail
}

func responseOK(code int) bool {
	return code == http.StatusOK ||
		code == http.StatusCreated ||
		code == http.StatusAccepted
}


================================================
FILE: api/server/middleware/authentication.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/errors"
	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/cmd/app/options"
	tokenutil "github.com/caoyingjunz/pixiu/pkg/util/token"
)

// Authentication 身份认证
func Authentication(o *options.Options) gin.HandlerFunc {
	keyBytes := []byte(o.ComponentConfig.Default.JWTKey)

	return func(c *gin.Context) {
		if o.ComponentConfig.Default.Mode.InDebug() {
			// Considered all as root user when running in debug mode.
			root, err := o.Factory.User().GetRoot(c)
			if err != nil {
				httputils.AbortFailedWithCode(c, http.StatusInternalServerError, err)
				return
			}

			httputils.SetUserToContext(c, root)
			return
		}

		if alwaysAllowPath.Has(c.Request.URL.Path) || allowCustomRequest(c) {
			return
		}

		if err := validate(c, o, keyBytes); err != nil {
			httputils.AbortFailedWithCode(c, http.StatusUnauthorized, err)
			return
		}
	}
}

func validate(c *gin.Context, o *options.Options, keyBytes []byte) error {
	token, err := extractToken(c, false)
	if err != nil {
		return err
	}
	claim, err := tokenutil.ParseToken(token, keyBytes)
	if err != nil {
		return err
	}

	existToken, err := o.Controller.User().GetLoginToken(c, claim.Id)
	if err != nil {
		return fmt.Errorf("未登陆或者密码被修改,请重新登陆")
	}
	if token != existToken {
		return fmt.Errorf("已被他人登陆")
	}

	user, err := o.Factory.User().Get(c, claim.Id)
	if err != nil {
		return err
	}
	if user == nil {
		return errors.ErrUnauthorized
	}
	httputils.SetUserToContext(c, user)

	return nil
}

// 从请求头中获取 token
func extractToken(c *gin.Context, ws bool) (string, error) {
	emptyFunc := func(t string) bool { return len(t) == 0 }
	if ws {
		wsToken := c.GetHeader("Sec-WebSocket-Protocol")
		if emptyFunc(wsToken) {
			return "", fmt.Errorf("authorization header is not provided")
		}
		return wsToken, nil
	}

	token := c.GetHeader("Authorization")
	if emptyFunc(token) {
		return "", fmt.Errorf("authorization header is not provided")
	}
	fields := strings.Fields(token)
	if len(fields) != 2 {
		return "", fmt.Errorf("invalid authorization header format")
	}
	if fields[0] != "Bearer" {
		return "", fmt.Errorf("unsupported authorization type")
	}

	return fields[1], nil
}


================================================
FILE: api/server/middleware/authorization.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/api/server/router/cluster"
	"github.com/caoyingjunz/pixiu/api/server/router/proxy"
	"github.com/caoyingjunz/pixiu/cmd/app/options"
	ctrlutil "github.com/caoyingjunz/pixiu/pkg/controller/util"
	"github.com/caoyingjunz/pixiu/pkg/db/model"
)

// HTTP method to operation
var operationsMap = map[string]model.Operation{
	http.MethodGet:    model.OpRead,
	http.MethodPost:   model.OpCreate,
	http.MethodPatch:  model.OpUpdate,
	http.MethodPut:    model.OpUpdate,
	http.MethodDelete: model.OpDelete,
}

// Authorization 鉴权
func Authorization(o *options.Options) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 允许请求直接通过
		if o.ComponentConfig.Default.Mode.InDebug() || alwaysAllowPath.Has(c.Request.URL.Path) || allowCustomRequest(c) {
			return
		}

		user, err := httputils.GetUserFromRequest(c)
		if err != nil {
			httputils.AbortFailedWithCode(c, http.StatusMethodNotAllowed, err)
			return
		}

		switch user.Status {
		case 1:
			// status 为 1,表示用户只读模式, 只读模式只允许查询请求
			if c.Request.Method != http.MethodGet && c.Request.Method != http.MethodOptions {
				httputils.AbortFailedWithCode(c, http.StatusForbidden, fmt.Errorf("无操作权限"))
				return
			}
		case 2:
			// 禁用用户无法进行任何操作
			httputils.AbortFailedWithCode(c, http.StatusForbidden, fmt.Errorf("用户已被禁用"))
			return
		}

		// Proxy path should be skipped now.
		// TODO: get object and ID from proxy path
		if proxy.IsProxyPath(c) || cluster.IsKubeProxyPath(c) || cluster.IsHelmPath(c) {
			return
		}

		obj, id, ok := httputils.GetObjectFromRequest(c)
		if !ok {
			return
		}

		op := operationsMap[c.Request.Method]
		// load policy for consistency
		// ref: https://github.com/casbin/casbin/issues/679#issuecomment-761525328
		if err := o.Enforcer.LoadPolicy(); err != nil {
			httputils.AbortFailedWithCode(c, http.StatusInternalServerError, err)
			return
		}
		ok, err = o.Enforcer.Enforce(user.Name, obj, id, op.String())
		if err != nil {
			httputils.AbortFailedWithCode(c, http.StatusMethodNotAllowed, err)
			return
		}
		if !ok {
			httputils.AbortFailedWithCode(c, http.StatusForbidden, fmt.Errorf("无操作权限"))
		}
		if id != "" {
			return
		}
		// this is a list API
		if err := ctrlutil.SetIdRangeContext(c, o.Enforcer, user, obj); err != nil {
			httputils.AbortFailedWithCode(c, http.StatusInternalServerError, err)
		}
	}
}


================================================
FILE: api/server/middleware/cors.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import (
	"time"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

func Cors() gin.HandlerFunc {
	c := cors.Config{
		AllowAllOrigins: true,
		AllowMethods:    []string{"GET", "POST", "PUT", "DELETE", "PATCH"},
		AllowHeaders:    []string{"Content-Type", "Access-Token", "Authorization"},
		MaxAge:          6 * time.Hour,
	}

	return cors.New(c)

}


================================================
FILE: api/server/middleware/limiter.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import (
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/juju/ratelimit"
	"golang.org/x/time/rate"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/util/errors"
	"github.com/caoyingjunz/pixiu/pkg/util/lru"
)

const (
	capacity = 100
	quantum  = 20
	cap      = 200
)

// UserRateLimiter 针对每个用户的请求进行限速
// TODO 限速大小从配置中读取
func UserRateLimiter() gin.HandlerFunc {
	cache := lru.NewLRUCache(cap)

	return func(c *gin.Context) {
		clientIP := c.ClientIP()
		if !cache.Contains(clientIP) {
			cache.Add(clientIP, ratelimit.NewBucketWithQuantum(time.Second, capacity, quantum))
			return
		}
		// 通过 ClientIP 取出 bucket
		val := cache.Get(clientIP)
		if val == nil {
			return
		}

		// 判断是否还有可用的 bucket
		bucket := val.(*ratelimit.Bucket)
		if bucket.TakeAvailable(1) == 0 {
			httputils.AbortFailedWithCode(c, http.StatusForbidden, errors.ErrBusySystem)
		}
	}
}

func Limiter() gin.HandlerFunc {
	// 初始化一个限速器,每秒产生 1000 个令牌,桶的大小为 1000 个
	// 初始化状态桶是满的
	// TODO: 限速的值从配置或者环境变量中获取
	limiter := rate.NewLimiter(1000, 1000)

	return func(c *gin.Context) {
		if !limiter.Allow() {
			httputils.AbortFailedWithCode(c, http.StatusForbidden, errors.ErrBusySystem)
		}
	}
}


================================================
FILE: api/server/middleware/log.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import (
	"github.com/gin-contrib/requestid"
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/db"
	logutil "github.com/caoyingjunz/pixiu/pkg/util/log"
)

func Logger(cfg *logutil.LogOptions) gin.HandlerFunc {
	return func(c *gin.Context) {
		l := logutil.NewLogger(cfg)
		c.Set(db.SQLContextKey, new(db.SQLs)) // set SQL context key

		// 处理请求操作
		c.Next()

		l.WithLogFields(map[string]interface{}{
			"request_id":              requestid.Get(c),
			"method":                  c.Request.Method,
			"uri":                     c.Request.RequestURI,
			httputils.ResponseCodeKey: httputils.GetResponseCode(c),
			"client_ip":               c.ClientIP(),
		})
		l.Log(c, logutil.InfoLevel, httputils.GetRawError(c))
	}
}


================================================
FILE: api/server/middleware/middleware.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package middleware

import (
	"github.com/gin-contrib/requestid"
	"github.com/gin-gonic/gin"
	"k8s.io/apimachinery/pkg/util/sets"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/util"
)

var alwaysAllowPath sets.String

func init() {
	alwaysAllowPath = sets.NewString("/pixiu/users/login")
}

// 允许特定请求不经过验证
func allowCustomRequest(c *gin.Context) bool {
	// TODO: 其他请求
	return false
}

func InstallMiddlewares(o *options.Options) {
	// 依次进行跨域,日志,单用户限速,总量限速,验证,鉴权和审计
	o.HttpEngine.Use(
		requestid.New(requestid.WithGenerator(func() string {
			return util.GenerateRequestID()
		})),
		Cors(),
		Logger(&o.ComponentConfig.Default.LogOptions),
		UserRateLimiter(),
		Limiter(),
		Authentication(o),
		Authorization(o),
		Admission(),
		Audit(o),
	)
}


================================================
FILE: api/server/router/audit/audit.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package audit

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

type auditRouter struct {
	c controller.PixiuInterface
}

func NewRouter(o *options.Options) {
	router := &auditRouter{
		c: o.Controller,
	}
	router.initRoutes(o.HttpEngine)
}

func (a *auditRouter) initRoutes(httpEngine *gin.Engine) {
	auditRoute := httpEngine.Group("/pixiu/audits")
	{
		// get 日志
		auditRoute.GET("/:auditId", a.getAudit)
		auditRoute.GET("", a.listAudits)
	}
}


================================================
FILE: api/server/router/audit/audit_routes.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package audit

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type AuditMeta struct {
	AuditId int64 `uri:"auditId" binding:"required"`
}

func (a *auditRouter) getAudit(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt AuditMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = a.c.Audit().Get(c, opt.AuditId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (a *auditRouter) listAudits(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		listOption types.AuditListOptions
		err        error
	)
	if err = httputils.ShouldBindAny(c, nil, nil, &listOption); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = a.c.Audit().List(c, listOption); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/auth/auth.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package auth

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

const (
	AuthBasePath   = "/pixiu/auth"
	PolicySubPath  = "/policy"
	BindingSubPath = "/binding"
)

type authRouter struct {
	c controller.PixiuInterface
}

func NewRouter(o *options.Options) {
	router := &authRouter{
		c: o.Controller,
	}
	router.initRoutes(o.HttpEngine)
}

func (a *authRouter) initRoutes(ge *gin.Engine) {
	authRoute := ge.Group(AuthBasePath)
	{
		policyRoute := authRoute.Group(PolicySubPath)
		policyRoute.POST("", a.createPolicy)
		policyRoute.DELETE("", a.deletePolicy)
		policyRoute.GET("", a.listPolicies)
	}
	{
		bindingRoute := authRoute.Group(BindingSubPath)
		bindingRoute.POST("", a.createBinding)
		bindingRoute.DELETE("", a.deleteBinding)
		bindingRoute.GET("", a.listBindings)
	}
}


================================================
FILE: api/server/router/auth/auth_routes.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package auth

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type IdMeta struct {
	PolicyId int64 `uri:"policyId" binding:"required"`
}

func (a *authRouter) listPolicies(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		req types.ListRBACPolicyRequest
		err error
	)
	if err = c.ShouldBindQuery(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = a.c.Auth().ListRBACPolicies(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (a *authRouter) createPolicy(c *gin.Context) {
	r := httputils.NewResponse()
	var req types.RBACPolicyRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err := a.c.Auth().CreateRBACPolicy(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (a *authRouter) deletePolicy(c *gin.Context) {
	r := httputils.NewResponse()
	var req types.RBACPolicyRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err := a.c.Auth().DeleteRBACPolicy(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (a *authRouter) listBindings(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		req types.ListGroupBindingRequest
		err error
	)
	if err = c.ShouldBindQuery(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = a.c.Auth().ListGroupBindings(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (a *authRouter) createBinding(c *gin.Context) {
	r := httputils.NewResponse()
	var req types.GroupBindingRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err := a.c.Auth().CreateGroupBinding(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (a *authRouter) deleteBinding(c *gin.Context) {
	r := httputils.NewResponse()
	var req types.GroupBindingRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err := a.c.Auth().DeleteGroupBinding(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/cluster/cluster.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

const (
	kubeProxyBaseURL = "/pixiu/kubeproxy"
	helmBaseURL      = "/pixiu/helms"
	indexerBaseURL   = "/pixiu/indexer"
)

// clusterRouter is a router to talk with the cluster controller
type clusterRouter struct {
	c controller.PixiuInterface
}

// NewRouter initializes a new cluster router
func NewRouter(o *options.Options) {
	s := &clusterRouter{
		c: o.Controller,
	}
	s.initRoutes(o.HttpEngine)
}

func (cr *clusterRouter) initRoutes(httpEngine *gin.Engine) {
	clusterRoute := httpEngine.Group("/pixiu/clusters")
	{
		clusterRoute.POST("", cr.createCluster)
		clusterRoute.PUT("/:clusterId", cr.updateCluster)
		clusterRoute.DELETE("/:clusterId", cr.deleteCluster)
		clusterRoute.GET("/:clusterId", cr.getCluster)
		clusterRoute.GET("", cr.listClusters)

		// 检查 kubernetes 的连通性
		clusterRoute.POST("/ping", cr.pingCluster)

		// 设置集群的删除保护模式
		clusterRoute.POST("/protect/:clusterId", cr.protectCluster)
	}

	// 调用 kubernetes 对象
	kubeRoute := httpEngine.Group(kubeProxyBaseURL)
	{
		// 获取指定对象的日志
		kubeRoute.GET("/clusters/:cluster/namespaces/:namespace/pods/:pod/log", cr.watchPodLog)
		// Deprecated 聚合 events
		kubeRoute.GET("/clusters/:cluster/namespaces/:namespace/name/:name/kind/:kind/events", cr.aggregateEvents)
		// 获取指定对象的 events,支持事件聚合
		kubeRoute.GET("/clusters/:cluster/api/v1/events", cr.getEventList)

		// pod ws
		kubeRoute.GET("/ws", cr.webShell)
		// node ws
		kubeRoute.GET("/nodes/ws", cr.nodeWebShell)

		// 重启Job action=rerun
		kubeRoute.POST("/clusters/:cluster/namespaces/:namespace/jobs/:name", cr.ReRunJob)
	}

	// 从 pixiu 缓存中获取 kubernetes 对象
	//indexerRoute := httpEngine.Group(indexerBaseURL)
	//{
	//	// 从缓存中获取指定对象
	//	indexerRoute.GET("/clusters/:cluster/resources/:resource/namespaces/:namespace/name/:name", cr.getIndexerResource)
	//	// 从缓存中获取对象列表
	//	indexerRoute.GET("/clusters/:cluster/resources/:resource/namespaces/:namespace", cr.listIndexerResources)
	//}
}


================================================
FILE: api/server/router/cluster/cluster_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type IdMeta struct {
	ClusterId int64 `uri:"clusterId" binding:"required"`
}

// CreateCluster godoc
//
//	@Summary      Create a cluster
//	@Description  Create by a json cluster
//	@Tags         Clusters
//	@Accept       json
//	@Produce      json
//	@Param        cluster  body      types.Cluster  true  "Create cluster"
//	@Success      200      {object}  httputils.Response
//	@Failure      400      {object}  httputils.Response
//	@Failure      404      {object}  httputils.Response
//	@Failure      500      {object}  httputils.Response
//	@Router       /pixiu/clusters/ [post]
//	@Security     Bearer
func (cr *clusterRouter) createCluster(c *gin.Context) {
	r := httputils.NewResponse()

	var req types.CreateClusterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err := cr.c.Cluster().Create(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// UpdateCluster godoc
//
//	@Summary      Update an cluster
//	@Description  Update by json cluster
//	@Tags         Clusters
//	@Accept       json
//	@Produce      json
//	@Param        clusterId  path      int            true  "Cluster ID"
//	@Param        cluster    body      types.Cluster  true  "Update cluster"
//	@Success      200        {object}  httputils.Response
//	@Failure      400        {object}  httputils.Response
//	@Failure      404        {object}  httputils.Response
//	@Failure      500        {object}  httputils.Response
//	@Router       /pixiu/clusters/{clusterId} [put]
//	@Security     Bearer
func (cr *clusterRouter) updateCluster(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		idMeta IdMeta
		err    error
	)
	if err = c.ShouldBindUri(&idMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	var req types.UpdateClusterRequest
	if err = c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if err = cr.c.Cluster().Update(c, idMeta.ClusterId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// DeleteCluster godoc
//
//	@Summary      Delete cluster by clusterId
//	@Description  Delete by cloud cluster ID
//	@Tags         Clusters
//	@Accept       json
//	@Produce      json
//	@Param        clusterId  path      int  true  "Cluster ID"
//	@Success      200        {object}  httputils.Response
//	@Failure      400        {object}  httputils.Response
//	@Failure      404        {object}  httputils.Response
//	@Failure      500        {object}  httputils.Response
//	@Router       /pixiu/clusters/{clusterId} [delete]
//	@Security     Bearer
func (cr *clusterRouter) deleteCluster(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		idMeta IdMeta
		err    error
	)
	if err = c.ShouldBindUri(&idMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if err = cr.c.Cluster().Delete(c, idMeta.ClusterId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	httputils.SetSuccess(c, r)
}

// GetCluster godoc
//
//	@Summary      Get Cluster by clusterId
//	@Description  Get by cloud cluster ID
//	@Tags         Clusters
//	@Accept       json
//	@Produce      json
//	@Param        clusterId  path      int  true  "Cluster ID"
//	@Success      200        {object}  httputils.Response{result=types.Cluster}
//	@Failure      400        {object}  httputils.Response
//	@Failure      404        {object}  httputils.Response
//	@Failure      500        {object}  httputils.Response
//	@Router       /pixiu/clusters/{clusterId} [get]
//	@Security     Bearer
func (cr *clusterRouter) getCluster(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		idMeta IdMeta
		err    error
	)
	if err = c.ShouldBindUri(&idMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if r.Result, err = cr.c.Cluster().Get(c, idMeta.ClusterId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// ListClusters godoc
//
//	@Summary      List clusters
//	@Description  List clusters with pagination and filter
//	@Tags         Clusters
//	@Accept       json
//	@Produce      json
//	@Param        page          query     int     false  "Page number (1-based)"
//	@Param        limit         query     int     false  "Page size"
//	@Param        nameSelector  query     string  false  "Fuzzy match on alias_name"
//	@Param        status        query     int     false  "Cluster status (0-4)"
//	@Success      200  {object}  httputils.Response{result=types.PageResponse}
//	@Failure      400  {object}  httputils.Response
//	@Failure      500  {object}  httputils.Response
//	@Router       /pixiu/clusters [get]
//	@Security     Bearer
func (cr *clusterRouter) listClusters(c *gin.Context) {
	r := httputils.NewResponse()

	var req types.ListClusterRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	var err error
	if r.Result, err = cr.c.Cluster().List(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// PingCluster godoc
//
//	@Summary      Ping cluster
//	@Description  Do ping
//	@Tags         Clusters
//	@Accept       json
//	@Produce      json
//	@Param        clusterId  path      int  true  "Cluster ID"
//	@Success      200        {array}   httputils.Response
//	@Failure      400        {object}  httputils.Response
//	@Failure      404        {object}  httputils.Response
//	@Failure      500        {object}  httputils.Response
//	@Router       /pixiu/clusters/{clusterId}/ping [get]
//	@Security     Bearer
func (cr *clusterRouter) pingCluster(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		cluster types.Cluster
		err     error
	)
	if err = c.ShouldBindJSON(&cluster); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = cr.c.Cluster().Ping(c, cluster.KubeConfig); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (cr *clusterRouter) protectCluster(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		idMeta IdMeta
		req    types.ProtectClusterRequest
		err    error
	)
	if err = httputils.ShouldBindAny(c, &req, &idMeta, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = cr.c.Cluster().Protect(c, idMeta.ClusterId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (cr *clusterRouter) aggregateEvents(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		optMeta struct {
			Cluster   string `uri:"cluster" binding:"required"`
			Namespace string `uri:"namespace" binding:"required"`
			Name      string `uri:"name" binding:"required"`
			Kind      string `uri:"kind" binding:"required"`
		}
		err error
	)

	if err = c.ShouldBindUri(&optMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = cr.c.Cluster().AggregateEvents(c, optMeta.Cluster, optMeta.Namespace, optMeta.Name, optMeta.Kind); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (cr *clusterRouter) getEventList(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		opts struct {
			Cluster string `uri:"cluster" binding:"required"`
		}
		eventOpt types.EventOptions
		err      error
	)
	if err = httputils.ShouldBindAny(c, nil, &opts, &eventOpt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = cr.c.Cluster().GetEventList(c, opts.Cluster, eventOpt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (cr *clusterRouter) watchPodLog(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opts struct {
			Cluster   string `uri:"cluster" binding:"required"`
			Namespace string `uri:"namespace" binding:"required"`
			Pod       string `uri:"pod" binding:"required"` //pod name
		}
		logOpt types.PodLogOptions
		err    error
	)
	if err = httputils.ShouldBindAny(c, nil, &opts, &logOpt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	// websocket
	if err = cr.c.Cluster().WatchPodLog(c, opts.Cluster, opts.Namespace, opts.Pod, logOpt.Container, logOpt.TailLines, c.Writer, c.Request); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
}


================================================
FILE: api/server/router/cluster/helper.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"strings"

	"github.com/gin-gonic/gin"
)

func IsKubeProxyPath(c *gin.Context) bool {
	return strings.HasPrefix(c.Request.URL.Path, kubeProxyBaseURL)
}

func IsHelmPath(c *gin.Context) bool {
	return strings.HasPrefix(c.Request.URL.Path, helmBaseURL)
}


================================================
FILE: api/server/router/cluster/informer.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type ResourceMeta struct {
	Cluster   string `uri:"cluster" binding:"required"`
	Resource  string `uri:"resource" binding:"required"`
	Namespace string `uri:"namespace"`
	Name      string `uri:"name"`
}

func (cr *clusterRouter) getIndexerResource(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		resourceMeta ResourceMeta
		err          error
	)
	if err = httputils.ShouldBindAny(c, nil, &resourceMeta, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = cr.c.Cluster().GetIndexerResource(c, resourceMeta.Cluster, resourceMeta.Resource, resourceMeta.Namespace, resourceMeta.Name); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (cr *clusterRouter) listIndexerResources(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		resourceMeta ResourceMeta
		listOption   types.ListOptions // 分页设置
		err          error
	)
	if err = httputils.ShouldBindAny(c, nil, &resourceMeta, &listOption); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = cr.c.Cluster().ListIndexerResources(c, resourceMeta.Cluster, resourceMeta.Resource, resourceMeta.Namespace, listOption); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/cluster/proxy.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type Action struct {
	Act             string `form:"action" binding:"required"`
	ResourceVersion string `form:"resourceVersion" binding:"required"`
}

func (cr *clusterRouter) ReRunJob(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		jobMeta types.PixiuObjectMeta
		action  Action
		err     error
	)
	if err = httputils.ShouldBindAny(c, nil, &jobMeta, &action); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = cr.c.Cluster().ReRunJob(c, jobMeta.Cluster, jobMeta.Namespace, jobMeta.Name, action.ResourceVersion); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/cluster/ws.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cluster

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

func (cr *clusterRouter) webShell(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err error
		opt types.WebShellOptions
	)
	if err = c.ShouldBindQuery(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = cr.c.Cluster().WsHandler(c, &opt, c.Writer, c.Request); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
}

func (cr *clusterRouter) nodeWebShell(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		sshConfig types.WebSSHRequest
		err       error
	)
	if err = httputils.ShouldBindAny(c, nil, nil, &sshConfig); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = cr.c.Cluster().WsNodeHandler(c, &sshConfig, c.Writer, c.Request); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
}


================================================
FILE: api/server/router/helm/helm.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package helm

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

const (
	helmBaseURL = "/pixiu/helms"
)

type helmRouter struct {
	c controller.PixiuInterface
}

func NewRouter(o *options.Options) {
	hr := &helmRouter{
		c: o.Controller,
	}
	hr.initRoutes(o.HttpEngine)
}

func (hr *helmRouter) initRoutes(httpEngine *gin.Engine) {

	helmRoute := httpEngine.Group(helmBaseURL)
	{
		// helm Repository
		helmRoute.POST("/repositories", hr.createRepository)
		helmRoute.PUT("/repositories/:id", hr.updateRepository)
		helmRoute.DELETE("/repositories/:id", hr.deleteRepository)
		helmRoute.GET("/repositories/:id", hr.getRepository)
		helmRoute.GET("/repositories", hr.listRepositories)

		helmRoute.GET("/repositories/:id/charts", hr.getRepoCharts)
		helmRoute.GET("/repositories/charts", hr.getRepoChartsByURL)
		helmRoute.GET("/repositories/values", hr.getChartValues)

		// Helm Release
		helmRoute.POST("/clusters/:cluster/namespaces/:namespace/releases", hr.InstallRelease)
		helmRoute.PUT("/clusters/:cluster/namespaces/:namespace/releases", hr.UpgradeRelease)
		helmRoute.DELETE("/clusters/:cluster/namespaces/:namespace/releases/:name", hr.UninstallRelease)
		helmRoute.GET("/clusters/:cluster/namespaces/:namespace/releases/:name", hr.GetRelease)
		helmRoute.GET("/clusters/:cluster/namespaces/:namespace/releases", hr.ListReleases)

		helmRoute.GET("/clusters/:cluster/namespaces/:namespace/releases/:name/history", hr.GetReleaseHistory)
		helmRoute.POST("/clusters/:cluster/namespaces/:namespace/releases/:name/rollback", hr.RollbackRelease)
	}
}


================================================
FILE: api/server/router/helm/release_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package helm

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

// GetRelease retrieves a release by its name in the specified namespace and cluster
//
// @Summary get a release
// @Description retrieves a release from the specified namespace and cluster
// @Tags helm
// @Accept json
// @Produce json
// @Param cluster path string true "Kubernetes cluster name"
// @Param namespace path string true "Kubernetes namespace"
// @Param name path string true "Release name"
// @Success 200 {object} httputils.Response{result=types.Release}
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /helm/releases/{cluster}/{namespace}/{name} [get]
func (hr *helmRouter) GetRelease(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err      error
		helmMeta types.PixiuObjectMeta
	)
	if err = c.ShouldBindUri(&helmMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if r.Result, err = hr.c.Helm().Release(helmMeta.Cluster, helmMeta.Namespace).Get(c, helmMeta.Name); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	httputils.SetSuccess(c, r)
}

// ListReleases lists all releases in the specified namespace and cluster
//
// @Summary list releases
// @Description lists all releases in the specified namespace and cluster
// @Tags helm
// @Accept json
// @Produce json
// @Param cluster path string true "Kubernetes cluster name"
// @Param namespace path string true "Kubernetes namespace"
// @Success 200 {object} httputils.Response{result=[]types.Release}
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /helm/releases/{cluster}/{namespace} [get]
func (hr *helmRouter) ListReleases(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err      error
		helmMeta types.PixiuObjectMeta
	)
	if err = c.ShouldBindUri(&helmMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if r.Result, err = hr.c.Helm().Release(helmMeta.Cluster, helmMeta.Namespace).List(c); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// InstallRelease installs a new release in the specified namespace and cluster
//
// @Summary install a release
// @Description installs a release in the specified Kubernetes namespace and cluster
// @Tags helm
// @Accept json
// @Produce json
// @Param cluster path string true "Kubernetes cluster name"
// @Param namespace path string true "Kubernetes namespace"
// @Param body body types.ReleaseForm true "Release information"
// @Success 200 {object} httputils.Response
// @Failure 400 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /helm/releases/{cluster}/{namespace} [post]
func (hr *helmRouter) InstallRelease(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err        error
		helmMeta   types.PixiuObjectMeta
		releaseOpt types.Release
	)
	if err = httputils.ShouldBindAny(c, &releaseOpt, &helmMeta, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if r.Result, err = hr.c.Helm().Release(helmMeta.Cluster, helmMeta.Namespace).Install(c, &releaseOpt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// UninstallRelease uninstalls a release from the specified namespace and cluster
//
// @Summary uninstall a release
// @Description uninstalls a release from the specified Kubernetes namespace and cluster
// @Tags helm
// @Accept json
// @Produce json
// @Param cluster path string true "Kubernetes cluster name"
// @Param namespace path string true "Kubernetes namespace"
// @Param name path string true "Release name"
// @Success 200 {object} httputils.Response
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /helm/releases/{cluster}/{namespace}/{name} [delete]
func (hr *helmRouter) UninstallRelease(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err      error
		helmMeta types.PixiuObjectMeta
	)
	if err = c.ShouldBindUri(&helmMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if r.Result, err = hr.c.Helm().Release(helmMeta.Cluster, helmMeta.Namespace).Uninstall(c, helmMeta.Name); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// UpgradeRelease upgrades a release in the specified namespace and cluster
//
// @Summary upgrade a release
// @Description upgrades a release in the specified Kubernetes namespace and cluster
// @Tags helm
// @Accept json
// @Produce json
// @Param cluster path string true "Kubernetes cluster name"
// @Param namespace path string true "Kubernetes namespace"
// @Param name path string true "Release name"
// @Param body body types.ReleaseForm true "Release information"
// @Success 200 {object} httputils.Response
// @Failure 400 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /helm/releases/{cluster}/{namespace}/{name} [put]
func (hr *helmRouter) UpgradeRelease(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err        error
		helmMeta   types.PixiuObjectMeta
		releaseOpt types.Release
	)
	if err = httputils.ShouldBindAny(c, &releaseOpt, &helmMeta, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if r.Result, err = hr.c.Helm().Release(helmMeta.Cluster, helmMeta.Namespace).Upgrade(c, &releaseOpt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// GetReleaseHistory retrieves the history of a release in the specified namespace and cluster
//
// @Summary get a release history
// @Description retrieves the history of a release from the specified Kubernetes namespace and cluster
// @Tags helm
// @Accept json
// @Produce json
// @Param cluster path string true "Kubernetes cluster name"
// @Param namespace path string true "Kubernetes namespace"
// @Param name path string true "Release name"
// @Success 200 {object} httputils.Response{result=types.ReleaseHistory}
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /helm/releases/history/{cluster}/{namespace}/{name} [get]
func (hr *helmRouter) GetReleaseHistory(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err      error
		helmMeta types.PixiuObjectMeta
	)
	if err = c.ShouldBindUri(&helmMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if r.Result, err = hr.c.Helm().Release(helmMeta.Cluster, helmMeta.Namespace).History(c, helmMeta.Name); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// RollbackRelease rolls back a release in the specified namespace and cluster to the specified revision
//
// @Summary rollback a release
// @Description rolls back a release from the specified Kubernetes namespace and cluster to the specified revision
// @Tags helm
// @Accept json
// @Produce json
// @Param cluster path string true "Kubernetes cluster name"
// @Param namespace path string true "Kubernetes namespace"
// @Param name path string true "Release name"
// @Param version query int true "Release revision"
// @Success 200 {object} httputils.Response
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /helm/releases/rollback/{cluster}/{namespace}/{name} [post]
func (hr *helmRouter) RollbackRelease(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err          error
		helmMeta     types.PixiuObjectMeta
		reverionMeta types.ReleaseHistory
	)
	if err = httputils.ShouldBindAny(c, nil, &helmMeta, &reverionMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if err = hr.c.Helm().Release(helmMeta.Cluster, helmMeta.Namespace).Rollback(c, helmMeta.Name, reverionMeta.Version); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/helm/respository_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package helm

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

// createRepository creates a new repository in the specified cluster
//
// @Summary create a repository
// @Description creates a new repository in the specified Kubernetes cluster
// @Tags repositories
// @Accept json
// @Produce json
// @Param cluster query string true "Kubernetes cluster name"
// @Param body body types.RepoForm true "Repository information"
// @Success 200 {object} httputils.Response
// @Failure 400 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /repositories [post]
func (hr *helmRouter) createRepository(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		err error
		req types.CreateRepository
	)
	if err = httputils.ShouldBindAny(c, &req, nil, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	if err = hr.c.Helm().Repository().Create(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// deleteRepository deletes a repository by its ID
//
// @Summary delete a repository by ID
// @Description deletes a repository from the system using the provided ID
// @Tags repositories
// @Accept json
// @Produce json
// @Param id path int true "Repository ID"
// @Success 200 {object} httputils.Response
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /repositories/{id} [delete]
func (hr *helmRouter) deleteRepository(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		err      error
		repoMeta types.RepoId
	)
	if err = c.ShouldBindUri(&repoMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = hr.c.Helm().Repository().Delete(c, repoMeta.Id); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// updateRepository updates a repository by its ID
//
// @Summary update a repository by ID
// @Description updates a repository in the system using the provided ID and update information
// @Tags repositories
// @Accept json
// @Produce json
// @Param id path int true "Repository ID"
// @Param body body types.RepoUpdateForm true "Repository update information"
// @Success 200 {object} httputils.Response
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
func (hr *helmRouter) updateRepository(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		err      error
		repoMeta types.RepoId
		formData types.UpdateRepository
	)
	if err = httputils.ShouldBindAny(c, &formData, &repoMeta, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = hr.c.Helm().Repository().Update(c, repoMeta.Id, &formData); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// getRepository retrieves a repository by its ID
//
// @Summary get a repository by ID
// @Description retrieves a repository from the system using the provided ID
// @Tags repositories
// @Accept json
// @Produce json
// @Param id path int true "Repository ID"
// @Success 200 {object} httputils.Response{result=types.Repository}
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /repositories/{id} [get]
func (hr *helmRouter) getRepository(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		err      error
		repoMeta types.RepoId
	)
	if err = c.ShouldBindUri(&repoMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = hr.c.Helm().Repository().Get(c, repoMeta.Id); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// listRepositories retrieves a list of all repositories
//
// @Summary list repositories
// @Description retrieves a list of all repositories in the system
// @Tags repositories
// @Accept json
// @Produce json
// @Success 200 {object} httputils.Response{result=[]types.Repository}
// @Failure 400 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /repositories [get]
func (hr *helmRouter) listRepositories(c *gin.Context) {
	r := httputils.NewResponse()
	var err error

	if r.Result, err = hr.c.Helm().Repository().List(c); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// getRepoCharts retrieves charts of a repository by its ID
//
// @Summary get repository charts by ID
// @Description retrieves charts associated with a repository from the system using the provided ID
// @Tags repositories
// @Accept json
// @Produce json
// @Param id path int true "Repository ID"
// @Success 200 {object} httputils.Response{result=model.ChartIndex}
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /repositories/{id}/charts [get]
func (hr *helmRouter) getRepoCharts(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err      error
		repoMeta types.RepoId
	)

	if err = c.ShouldBindUri(&repoMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = hr.c.Helm().Repository().GetChartsById(c, repoMeta.Id); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// getRepoChartsByURL retrieves charts of a repository by its URL
//
// @Summary get repository charts by URL
// @Description retrieves charts associated with a repository from the system using the provided URL
// @Tags repositories
// @Accept json
// @Produce json
// @Param url query string true "Repository URL"
// @Success 200 {object} httputils.Response{result=model.ChartIndex}
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /repositories/charts [get]
func (hr *helmRouter) getRepoChartsByURL(c *gin.Context) {
	r := httputils.NewResponse()
	var (
		err      error
		repoMeta types.RepoURL
	)

	if err = httputils.ShouldBindAny(c, nil, nil, &repoMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = hr.c.Helm().Repository().GetChartsByURL(c, repoMeta.Url); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// getChartValues retrieves the values of a specific chart version
//
// @Summary get chart values
// @Description retrieves values for a specific chart version using the provided chart name and version
// @Tags charts
// @Accept json
// @Produce json
// @Param chart query string true "Chart name"
// @Param version query string true "Chart version"
// @Success 200 {object} httputils.Response{result=types.ChartValues}
// @Failure 400 {object} httputils.Response
// @Failure 404 {object} httputils.Response
// @Failure 500 {object} httputils.Response
// @Router /repositories/chartvalues [get]
func (hr *helmRouter) getChartValues(c *gin.Context) {

	r := httputils.NewResponse()
	var (
		err      error
		repoMeta types.ChartValues
	)

	if err = httputils.ShouldBindAny(c, nil, nil, &repoMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = hr.c.Helm().Repository().GetChartValues(c, repoMeta.Chart, repoMeta.Version); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)

}


================================================
FILE: api/server/router/plan/config_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package plan

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type planConfigMeta struct {
	planMeta

	ConfigId int64 `uri:"configId" binding:"required"`
}

func (t *planRouter) createPlanConfig(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		req types.CreatePlanConfigRequest
		err error
	)
	if err = httputils.ShouldBindAny(c, &req, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().CreateConfig(c, opt.PlanId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) updatePlanConfig(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planConfigMeta
		req types.UpdatePlanConfigRequest
		err error
	)
	if err = httputils.ShouldBindAny(c, &req, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().UpdateConfig(c, opt.PlanId, opt.ConfigId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) deletePlanConfig(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planConfigMeta
		err error
	)
	if err = httputils.ShouldBindAny(c, nil, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().DeleteConfig(c, opt.PlanId, opt.ConfigId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) getPlanConfig(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		err error
	)
	if err = httputils.ShouldBindAny(c, nil, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = t.c.Plan().GetConfig(c, opt.PlanId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/plan/node_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package plan

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type planNodeMeta struct {
	planMeta `json:",inline"`

	NodeId int64 `uri:"nodeId" binding:"required"`
}

func (t *planRouter) createPlanNode(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		req types.CreatePlanNodeRequest
		err error
	)
	if err = httputils.ShouldBindAny(c, &req, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().CreateNode(c, opt.PlanId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) updatePlanNode(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planNodeMeta
		req types.UpdatePlanNodeRequest
		err error
	)
	if err = httputils.ShouldBindAny(c, &req, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().UpdateNode(c, opt.PlanId, opt.NodeId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) deletePlanNode(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planNodeMeta
		err error
	)
	if err = httputils.ShouldBindAny(c, nil, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().DeleteNode(c, opt.PlanId, opt.NodeId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) getPlanNode(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planNodeMeta
		err error
	)
	if err = httputils.ShouldBindAny(c, nil, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = t.c.Plan().GetNode(c, opt.PlanId, opt.NodeId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) listPlanNodes(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		err error
	)
	if err = httputils.ShouldBindAny(c, nil, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = t.c.Plan().ListNodes(c, opt.PlanId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/plan/plan.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package plan

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

type planRouter struct {
	c controller.PixiuInterface
}

func NewRouter(o *options.Options) {
	router := &planRouter{
		c: o.Controller,
	}
	router.initRoutes(o.HttpEngine)
}

func (t *planRouter) initRoutes(ginEngine *gin.Engine) {
	planRoute := ginEngine.Group("/pixiu/plans")
	{
		planRoute.POST("", t.createPlan)
		planRoute.PUT("/:planId", t.updatePlan)
		planRoute.DELETE("/:planId", t.deletePlan)
		planRoute.GET("/:planId", t.getPlan)
		planRoute.GET("", t.listPlans)

		planRoute.GET("/:planId/resources", t.getPlanWithSubResources)

		// 启动部署任务
		planRoute.POST("/:planId/start", t.startPlan)
		// 终止部署任务
		planRoute.POST("/:planId/stop", t.stopPlan)

		// 部署计划的节点API
		planRoute.POST("/:planId/nodes", t.createPlanNode)
		planRoute.PUT("/:planId/nodes/:nodeId", t.updatePlanNode)
		planRoute.DELETE("/:planId/nodes/:nodeId", t.deletePlanNode)
		planRoute.GET("/:planId/nodes/:nodeId", t.getPlanNode)
		planRoute.GET("/:planId/nodes", t.listPlanNodes)

		// 部署计划的部署配置
		planRoute.POST("/:planId/configs", t.createPlanConfig)
		planRoute.PUT("/:planId/configs/:configId", t.updatePlanConfig)
		planRoute.DELETE("/:planId/configs/:configId", t.deletePlanConfig)
		planRoute.GET("/:planId/configs", t.getPlanConfig)

		// 执行指定任务
		planRoute.POST("/:planId/tasks/:taskId", t.runTasks)
		// 查询任务列表
		planRoute.GET("/:planId/tasks", t.listTasks)
		// 实时查询任务进度
		planRoute.GET("/:planId/tasks/:taskId/logs", t.watchTaskLog)

		// 获取 os 与 os version
		planRoute.GET("/distributions", t.getDistributions)
	}
}


================================================
FILE: api/server/router/plan/plan_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package plan

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type planMeta struct {
	PlanId int64 `uri:"planId" binding:"required"`
}

type watchTaskLogMeta struct {
	PlanId int64 `uri:"planId" binding:"required"`
	TaskId int64 `uri:"taskId" binding:"required"`
}

type WatchMeta struct {
	Watch bool `form:"watch"`
}

// 创建部署计划,同时创建配置和节点
func (t *planRouter) createPlan(c *gin.Context) {
	r := httputils.NewResponse()

	var req types.CreatePlanRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err := t.c.Plan().Create(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) updatePlan(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		req types.UpdatePlanRequest
		err error
	)
	if err = httputils.ShouldBindAny(c, &req, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().Update(c, opt.PlanId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) deletePlan(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().Delete(c, opt.PlanId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) getPlan(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = t.c.Plan().Get(c, opt.PlanId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// getPlanWithSubResources
// 获取 plan
// 获取 configs
// 获取 nodes
func (t *planRouter) getPlanWithSubResources(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = t.c.Plan().GetWithSubResources(c, opt.PlanId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) listPlans(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		req types.ListPlanRequest
		err error
	)
	if err = c.ShouldBindQuery(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = t.c.Plan().List(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) startPlan(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().Start(c, opt.PlanId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *planRouter) stopPlan(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt planMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().Stop(c, opt.PlanId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

type DistributionsMeta struct {
	Centos    []string `json:"centos,omitempty"`
	Ubuntu    []string `json:"ubuntu,omitempty"`
	Debian    []string `json:"debian,omitempty"`
	OpenEuler []string `json:"openEuler,omitempty"`
	Rocky     []string `json:"rocky,omitempty"`
}

func (t *planRouter) getDistributions(c *gin.Context) {
	r := httputils.NewResponse()

	r.Result = &DistributionsMeta{
		Centos:    []string{"centos7"},
		Ubuntu:    []string{"ubuntu18.04", "ubuntu20.04", "ubuntu22.04"},
		Debian:    []string{"debian10", "debian11"},
		OpenEuler: []string{"openEuler22.03"},
		Rocky:     []string{"rocky8.5", "rocky9.2", "rocky9.3"},
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/plan/task_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package plan

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
)

type taskNodeMeta struct {
	planMeta `json:",inline"`

	TaskId int64 `uri:"taskId" binding:"required"`
}

func (t *planRouter) runTasks(c *gin.Context) {
	r := httputils.NewResponse()

	httputils.SetSuccess(c, r)
}

func (t *planRouter) listTasks(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt   planMeta
		watch WatchMeta
		err   error
	)
	if err = httputils.ShouldBindAny(c, nil, &opt, &watch); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	// 不是长连接请求则直接返回
	if !watch.Watch {
		if r.Result, err = t.c.Plan().ListTasks(c, opt.PlanId); err != nil {
			httputils.SetFailed(c, r, err)
			return
		}
		httputils.SetSuccess(c, r)
		return
	}

	// 长连接请求
	t.c.Plan().WatchTasks(c, opt.PlanId, c.Writer, c.Request)
}

func (t *planRouter) watchTaskLog(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt watchTaskLogMeta
		err error
	)
	if err = httputils.ShouldBindAny(c, nil, &opt, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Plan().WatchTaskLog(c, opt.PlanId, opt.TaskId, c.Writer, c.Request); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
}


================================================
FILE: api/server/router/proxy/helper.go
================================================
/*
Copyright 2024 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package proxy

import (
	"strings"

	"github.com/gin-gonic/gin"
)

// IsProxyPath returns true when the request path is a proxy one.
func IsProxyPath(c *gin.Context) bool {
	return strings.HasPrefix(c.Request.URL.Path, proxyBaseURL)
}


================================================
FILE: api/server/router/proxy/proxy.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package proxy

import (
	"context"
	"fmt"
	"net/url"

	"github.com/gin-gonic/gin"
	"k8s.io/apimachinery/pkg/util/proxy"
	"k8s.io/client-go/rest"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

const (
	proxyBaseURL = "/pixiu/proxy"
)

type proxyRouter struct {
	c controller.PixiuInterface
}

func NewRouter(o *options.Options) {
	s := &proxyRouter{
		c: o.Controller,
	}
	s.initRoutes(o.HttpEngine)
}

func (p *proxyRouter) initRoutes(ginEngine *gin.Engine) {
	proxyRoute := ginEngine.Group("/pixiu/")
	{
		proxyRoute.Any("/proxy/:clusterName/*act", p.proxyHandler)
	}
}

func (p *proxyRouter) proxyHandler(c *gin.Context) {
	resp := httputils.NewResponse()

	var cluster struct {
		Name string `uri:"clusterName" binding:"required"`
	}
	if err := c.ShouldBindUri(&cluster); err != nil {
		httputils.SetFailed(c, resp, err)
		return
	}

	name := cluster.Name
	config, err := p.c.Cluster().GetKubeConfigByName(context.TODO(), name)
	if err != nil {
		httputils.SetFailed(c, resp, fmt.Errorf("failed to get cluster %q kubeconfig", name))
		return
	}

	transport, err := rest.TransportFor(config)
	if err != nil {
		httputils.SetFailed(c, resp, err)
		return
	}
	target, err := p.parseTarget(*c.Request.URL, config.Host, name)
	if err != nil {
		httputils.SetFailed(c, resp, err)
		return
	}

	httpProxy := proxy.NewUpgradeAwareHandler(target, transport, false, false, nil)
	httpProxy.UpgradeTransport = proxy.NewUpgradeRequestRoundTripper(transport, transport)
	httpProxy.ServeHTTP(c.Writer, c.Request)
}

func (p *proxyRouter) parseTarget(target url.URL, host string, name string) (*url.URL, error) {
	kubeURL, err := url.Parse(host)
	if err != nil {
		return nil, err
	}

	// TODO: 检查 URL 是否规范
	target.Path = target.Path[len(proxyBaseURL+"/"+name):]

	target.Host = kubeURL.Host
	target.Scheme = kubeURL.Scheme
	return &target, nil
}


================================================
FILE: api/server/router/router.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package router

import (
	"embed"
	"net/http"

	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"

	// 导入 docs.json 文件
	_ "github.com/caoyingjunz/pixiu/api/docs"
	_ "github.com/caoyingjunz/pixiu/api/server/validator"

	"github.com/caoyingjunz/pixiu/api/server/middleware"
	"github.com/caoyingjunz/pixiu/api/server/router/audit"
	"github.com/caoyingjunz/pixiu/api/server/router/auth"
	"github.com/caoyingjunz/pixiu/api/server/router/cluster"
	"github.com/caoyingjunz/pixiu/api/server/router/helm"
	"github.com/caoyingjunz/pixiu/api/server/router/plan"
	"github.com/caoyingjunz/pixiu/api/server/router/proxy"
	"github.com/caoyingjunz/pixiu/api/server/router/tenant"
	"github.com/caoyingjunz/pixiu/api/server/router/user"
	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/static"
)

type RegisterFunc func(o *options.Options)

//go:embed static
var EmbedFS embed.FS

func InstallRouters(o *options.Options) {
	fs := []RegisterFunc{
		middleware.InstallMiddlewares,
		cluster.NewRouter,
		helm.NewRouter,
		proxy.NewRouter,
		tenant.NewRouter,
		user.NewRouter,
		plan.NewRouter,
		audit.NewRouter,
		auth.NewRouter,
	}

	install(o, fs...)

	// StaticFiles 启用前端集成
	o.HttpEngine.Use(static.Serve("/", static.LocalFile(o.ComponentConfig.Default.StaticFiles, true)))

	// 启动健康检查
	o.HttpEngine.GET("/healthz", func(c *gin.Context) { c.String(http.StatusOK, "ok") })
	// 启动 APIs 服务
	o.HttpEngine.GET("/api-ref/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}

func install(o *options.Options, fs ...RegisterFunc) {
	for _, f := range fs {
		f(o)
	}
}


================================================
FILE: api/server/router/static/index.html
================================================
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>欢迎使用 Pixiu</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f7f7f7;
            color: #333;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            text-align: center;
        }
        .container {
            width: 100%; /* 占满整个屏幕宽度 */
            height: 100vh; /* 占满整个屏幕高度 */
            padding: 20px;
            background-color: #fff;
            border-radius: 0; /* 移除圆角 */
            box-shadow: none; /* 移除阴影 */
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
<div class="container">
    <h1>欢迎使用 Pixiu</h1>
</div>
</body>
</html>

================================================
FILE: api/server/router/tenant/tenant.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tenant

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

type tenantRouter struct {
	c controller.PixiuInterface
}

func NewRouter(o *options.Options) {
	router := &tenantRouter{
		c: o.Controller,
	}
	router.initRoutes(o.HttpEngine)
}

func (t *tenantRouter) initRoutes(ginEngine *gin.Engine) {
	tenantRoute := ginEngine.Group("/pixiu/tenants")
	{
		tenantRoute.POST("", t.createTenant)
		tenantRoute.PUT("/:tenantId", t.updateTenant)
		tenantRoute.DELETE("/:tenantId", t.deleteTenant)
		tenantRoute.GET("/:tenantId", t.getTenant)
		tenantRoute.GET("", t.listTenants)
	}
}


================================================
FILE: api/server/router/tenant/tenant_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tenant

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type TenantMeta struct {
	TenantId int64 `uri:"tenantId" binding:"required"`
}

func (t *tenantRouter) createTenant(c *gin.Context) {
	r := httputils.NewResponse()

	var req types.CreateTenantRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err := t.c.Tenant().Create(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *tenantRouter) updateTenant(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt TenantMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	var req types.UpdateTenantRequest
	if err = c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Tenant().Update(c, opt.TenantId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *tenantRouter) deleteTenant(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt TenantMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = t.c.Tenant().Delete(c, opt.TenantId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *tenantRouter) getTenant(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		opt TenantMeta
		err error
	)
	if err = c.ShouldBindUri(&opt); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = t.c.Tenant().Get(c, opt.TenantId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

func (t *tenantRouter) listTenants(c *gin.Context) {
	r := httputils.NewResponse()

	var err error
	if r.Result, err = t.c.Tenant().List(c); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}


================================================
FILE: api/server/router/user/user.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package user

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/cmd/app/options"
	"github.com/caoyingjunz/pixiu/pkg/controller"
)

type userRouter struct {
	c controller.PixiuInterface
}

func NewRouter(o *options.Options) {
	router := &userRouter{
		c: o.Controller,
	}
	router.initRoutes(o.HttpEngine)
}

func (u *userRouter) initRoutes(httpEngine *gin.Engine) {
	// TODO: Base pixiu 后续作为常量定义
	userRoute := httpEngine.Group("/pixiu/users")
	{
		userRoute.POST("", u.createUser)
		userRoute.PUT("/:userId", u.updateUser)
		userRoute.DELETE("/:userId", u.deleteUser)
		userRoute.GET("/:userId", u.getUser)
		userRoute.GET("", u.listUsers)

		// 用户修改密码或者管理员重置密码
		userRoute.PUT("/:userId/password", u.updatePassword)

		// 用户的登陆或者退出
		userRoute.POST("/login", u.login)
		userRoute.POST("/:userId/logout", u.logout)
	}
}


================================================
FILE: api/server/router/user/user_routes.go
================================================
/*
Copyright 2021 The Pixiu Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package user

import (
	"github.com/gin-gonic/gin"

	"github.com/caoyingjunz/pixiu/api/server/httputils"
	"github.com/caoyingjunz/pixiu/pkg/types"
)

type IdMeta struct {
	UserId int64 `uri:"userId" binding:"required"`
}

// CreateUser godoc
//
//	@Summary      Create a user
//	@Description  Create by a json user
//	@Tags         Users
//	@Accept       json
//	@Produce      json
//	@Param        user  body      types.CreateUserRequest  true  "Create user"
//	@Success      200   {object}  httputils.Response
//	@Failure      400   {object}  httputils.Response
//	@Failure      404   {object}  httputils.Response
//	@Failure      500   {object}  httputils.Response
//	@Router       /pixiu/users/ [post]
//	              @Security  Bearer
func (u *userRouter) createUser(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		req types.CreateUserRequest
		err error
	)
	if err = c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = u.c.User().Create(c, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// UpdateUser godoc
//
//	@Summary      Update an user
//	@Description  Update by json user
//	@Tags         Users
//	@Accept       json
//	@Produce      json
//	@Param        userId  path      int                      true  "User ID"
//	@Param        user    body      types.UpdateUserRequest  true  "Update user"
//	@Success      200     {object}  httputils.Response
//	@Failure      400     {object}  httputils.Response
//	@Failure      404     {object}  httputils.Response
//	@Failure      500     {object}  httputils.Response
//	@Router       /pixiu/users/{userId} [put]
//	              @Security  Bearer
func (u *userRouter) updateUser(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		idMeta IdMeta
		req    types.UpdateUserRequest
		err    error
	)
	if err = httputils.ShouldBindAny(c, &req, &idMeta, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = u.c.User().Update(c, idMeta.UserId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// UpdateUserPassword godoc
//
//	@Summary      Update user password
//	@Description  Update by json user
//	@Tags         Users
//	@Accept       json
//	@Produce      json
//	@Param        userId  path      int                              true  "User ID"
//	@Param        user    body      types.UpdateUserPasswordRequest  true  "Update user password"
//	@Success      200     {object}  httputils.Response
//	@Failure      400     {object}  httputils.Response
//	@Failure      404     {object}  httputils.Response
//	@Failure      500     {object}  httputils.Response
//	@Router       /pixiu/users/password [put]
//	              @Security  Bearer
func (u *userRouter) updatePassword(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		idMeta IdMeta
		req    types.UpdateUserPasswordRequest
		err    error
	)
	if err = httputils.ShouldBindAny(c, &req, &idMeta, nil); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = u.c.User().UpdatePassword(c, idMeta.UserId, &req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// DeleteUser godoc
//
//	@Summary      Delete user by userId
//	@Description  Delete by userID
//	@Tags         Users
//	@Accept       json
//	@Produce      json
//	@Param        userId  path      int  true  "User ID"
//	@Success      200     {object}  httputils.Response
//	@Failure      400     {object}  httputils.Response
//	@Failure      404     {object}  httputils.Response
//	@Failure      500     {object}  httputils.Response
//	@Router       /pixiu/users/{userId} [delete]
//	              @Security  Bearer
func (u *userRouter) deleteUser(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		idMeta IdMeta
		err    error
	)
	if err = c.ShouldBindUri(&idMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if err = u.c.User().Delete(c, idMeta.UserId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// Getuser godoc
//
//	@Summary      Get user by userId
//	@Description  Get by user ID
//	@Tags         Users
//	@Accept       json
//	@Produce      json
//	@Param        userId  path      int  true  "User ID"
//	@Success      200     {object}  httputils.Response{result=types.User}
//	@Failure      400     {object}  httputils.Response
//	@Failure      404     {object}  httputils.Response
//	@Failure      500     {object}  httputils.Response
//	@Router       /pixiu/users/{userId} [get]
//	              @Security  Bearer
func (u *userRouter) getUser(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		idMeta IdMeta
		err    error
	)
	if err = c.ShouldBindUri(&idMeta); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	if r.Result, err = u.c.User().Get(c, idMeta.UserId); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// Listusers godoc
//
//	@Summary      List users
//	@Description  List users
//	@Tags         Users
//	@Accept       json
//	@Produce      json
//	@Success      200  {array}   httputils.Response{result=[]types.User}
//	@Failure      400  {object}  httputils.Response
//	@Failure      404  {object}  httputils.Response
//	@Failure      500  {object}  httputils.Response
//	@Router       /pixiu/users [get]
//	              @Security  Bearer
func (u *userRouter) listUsers(c *gin.Context) {
	r := httputils.NewResponse()
	var req types.ListUserRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	var err error
	r.Result, err = u.c.User().List(c, &req)
	if err != nil {
		httputils.SetFailed(c, r, err)
		return
	}

	httputils.SetSuccess(c, r)
}

// Login godoc
//
//	@Summary      User login
//	@Description  Login by a json user
//	@Tags         Login
//	@Accept       json
//	@Produce      json
//	@Param        user  body      types.LoginRequest  true  "User login"
//	@Success      200   {object}  httputils.Response
//	@Failure      400   {object}  httputils.Response
//	@Failure      404   {object}  httputils.Response
//	@Failure      500   {object}  httputils.Response
//	@Router       /pixiu/users/login [post]
func (u *userRouter) login(c *gin.Context) {
	r := httputils.NewResponse()

	var (
		req types.LoginRequest
		err error
	)
	if err = c.ShouldBindJSON(&req); err != nil {
		httputils.SetFailed(c, r, err)
		return
	}
	loginResp, err := u.c.User().Login(c, &
Download .txt
gitextract__nbx67ym/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── build-webshell-image.yml
│       ├── ci.yml
│       └── docker-image.yml
├── .gitignore
├── Makefile
├── README.md
├── api/
│   ├── docs/
│   │   ├── docs.go
│   │   ├── swagger.json
│   │   └── swagger.yaml
│   └── server/
│       ├── errors/
│       │   └── errors.go
│       ├── httpstatus/
│       │   └── status.go
│       ├── httputils/
│       │   ├── docs.go
│       │   ├── httputils.go
│       │   └── httputils_test.go
│       ├── middleware/
│       │   ├── admission.go
│       │   ├── audit.go
│       │   ├── authentication.go
│       │   ├── authorization.go
│       │   ├── cors.go
│       │   ├── limiter.go
│       │   ├── log.go
│       │   └── middleware.go
│       ├── router/
│       │   ├── audit/
│       │   │   ├── audit.go
│       │   │   └── audit_routes.go
│       │   ├── auth/
│       │   │   ├── auth.go
│       │   │   └── auth_routes.go
│       │   ├── cluster/
│       │   │   ├── cluster.go
│       │   │   ├── cluster_routes.go
│       │   │   ├── helper.go
│       │   │   ├── informer.go
│       │   │   ├── proxy.go
│       │   │   └── ws.go
│       │   ├── helm/
│       │   │   ├── helm.go
│       │   │   ├── release_routes.go
│       │   │   └── respository_routes.go
│       │   ├── plan/
│       │   │   ├── config_routes.go
│       │   │   ├── node_routes.go
│       │   │   ├── plan.go
│       │   │   ├── plan_routes.go
│       │   │   └── task_routes.go
│       │   ├── proxy/
│       │   │   ├── helper.go
│       │   │   └── proxy.go
│       │   ├── router.go
│       │   ├── static/
│       │   │   └── index.html
│       │   ├── tenant/
│       │   │   ├── tenant.go
│       │   │   └── tenant_routes.go
│       │   └── user/
│       │       ├── user.go
│       │       └── user_routes.go
│       └── validator/
│           ├── helper.go
│           ├── password.go
│           ├── rbac.go
│           └── validator.go
├── cmd/
│   ├── app/
│   │   ├── config/
│   │   │   └── config.go
│   │   ├── options/
│   │   │   └── options.go
│   │   └── server.go
│   └── pixiuserver.go
├── config.yaml
├── deploy/
│   ├── README.md
│   └── pixiu/
│       ├── .helmignore
│       ├── Chart.yaml
│       ├── templates/
│       │   ├── NOTES.txt
│       │   ├── _helpers.tpl
│       │   ├── configmap.yaml
│       │   ├── deployment.yaml
│       │   ├── hpa.yaml
│       │   ├── ingress.yaml
│       │   ├── service.yaml
│       │   └── serviceaccount.yaml
│       └── values.yaml
├── docker/
│   ├── Dockerfile
│   ├── Dockerfile-toolbox
│   └── start.sh
├── docs/
│   ├── OWNERS
│   ├── README.md
│   ├── apis.md
│   └── sql.md
├── go.mod
├── go.sum
├── hack/
│   ├── tools/
│   │   └── licfmt/
│   │       └── licfmt.go
│   ├── update-gofmt.sh
│   ├── update-image.sh
│   └── verify-gofmt.sh
├── install.md
├── pkg/
│   ├── client/
│   │   ├── cache.go
│   │   ├── client.go
│   │   ├── helm.go
│   │   ├── task.go
│   │   ├── token_cache.go
│   │   └── user_cache.go
│   ├── controller/
│   │   ├── audit/
│   │   │   └── audit.go
│   │   ├── auth/
│   │   │   └── auth.go
│   │   ├── cluster/
│   │   │   ├── cluster.go
│   │   │   ├── informer.go
│   │   │   ├── util.go
│   │   │   └── ws.go
│   │   ├── controller.go
│   │   ├── helm/
│   │   │   ├── helm.go
│   │   │   ├── releases.go
│   │   │   └── repository.go
│   │   ├── plan/
│   │   │   ├── bootstrap_servers.go
│   │   │   ├── checker.go
│   │   │   ├── deploy.go
│   │   │   ├── plan.go
│   │   │   ├── plan_config.go
│   │   │   ├── plan_node.go
│   │   │   ├── plan_task.go
│   │   │   ├── register.go
│   │   │   ├── render.go
│   │   │   └── worker.go
│   │   ├── tenant/
│   │   │   └── tenant.go
│   │   ├── user/
│   │   │   ├── user.go
│   │   │   └── user_test.go
│   │   └── util/
│   │       └── util.go
│   ├── db/
│   │   ├── audit.go
│   │   ├── cluster.go
│   │   ├── factory.go
│   │   ├── logger.go
│   │   ├── migrator.go
│   │   ├── model/
│   │   │   ├── audit.go
│   │   │   ├── cluster.go
│   │   │   ├── model.go
│   │   │   ├── pixiu/
│   │   │   │   └── model.go
│   │   │   ├── plan.go
│   │   │   ├── rbac.go
│   │   │   ├── rbac_test.go
│   │   │   ├── repository.go
│   │   │   ├── tenant.go
│   │   │   └── user.go
│   │   ├── options.go
│   │   ├── plan.go
│   │   ├── repository.go
│   │   ├── tenant.go
│   │   └── user.go
│   ├── jobmanager/
│   │   ├── audit_cleaner.go
│   │   ├── cluster_syncer.go
│   │   ├── context.go
│   │   └── manager.go
│   ├── static/
│   │   ├── localfile.go
│   │   └── static.go
│   ├── types/
│   │   ├── helm.go
│   │   ├── meta.go
│   │   ├── request.go
│   │   └── types.go
│   └── util/
│       ├── container/
│       │   └── container.go
│       ├── errors/
│       │   └── errors.go
│       ├── log/
│       │   └── log.go
│       ├── lru/
│       │   └── lru.go
│       ├── ssh/
│       │   └── ssh.go
│       ├── token/
│       │   └── token.go
│       ├── util.go
│       ├── util_test.go
│       └── uuid/
│           └── uuid.go
└── template/
    ├── globals.go
    ├── hosts.go
    └── multinode.go
Download .txt
SYMBOL INDEX (1054 symbols across 118 files)

FILE: api/docs/docs.go
  constant docTemplate (line 23) | docTemplate = `{
  function init (line 908) | func init() {

FILE: api/server/errors/errors.go
  type Error (line 25) | type Error struct
    method Error (line 30) | func (e Error) Error() string {
  function NewError (line 34) | func NewError(err error, code int) Error {

FILE: api/server/httputils/docs.go
  type HttpOK (line 20) | type HttpOK struct
  type HttpError (line 26) | type HttpError struct

FILE: api/server/httputils/httputils.go
  type Response (line 34) | type Response struct
    method SetCode (line 40) | func (r *Response) SetCode(c int) {
    method SetMessage (line 44) | func (r *Response) SetMessage(m interface{}) {
    method SetMessageWithCode (line 53) | func (r *Response) SetMessageWithCode(m interface{}, c int) {
    method Error (line 58) | func (r *Response) Error() string {
    method String (line 62) | func (r *Response) String() string {
  function NewResponse (line 71) | func NewResponse() *Response {
  function SetSuccess (line 76) | func SetSuccess(c *gin.Context, r *Response) {
  function SetFailed (line 83) | func SetFailed(c *gin.Context, r *Response, err error) {
  function setFailedWithCode (line 95) | func setFailedWithCode(c *gin.Context, r *Response, code int, err error) {
  function setFailedWithValidationError (line 101) | func setFailedWithValidationError(c *gin.Context, r *Response, e string) {
  function AbortFailedWithCode (line 108) | func AbortFailedWithCode(c *gin.Context, code int, err error) {
  function ShouldBindAny (line 116) | func ShouldBindAny(c *gin.Context, jsonObject interface{}, uriObject int...
  constant userKey (line 136) | userKey = "user"
  function GetUserFromRequest (line 138) | func GetUserFromRequest(ctx context.Context) (*model.User, error) {
  function GetUserIdFromContext (line 151) | func GetUserIdFromContext(ctx context.Context) (int64, error) {
  function SetUserToContext (line 159) | func SetUserToContext(c *gin.Context, user *model.User) {
  function GetObjectFromRequest (line 163) | func GetObjectFromRequest(c *gin.Context) (string, string, bool) {
  function getObjectFromRequest (line 169) | func getObjectFromRequest(path string) (obj, sid string, ok bool) {
  constant objIDsKey (line 188) | objIDsKey = "objIDs"
  function SetIdRangeContext (line 191) | func SetIdRangeContext(c *gin.Context, ids []int64) {
  function GetIdRangeFromListReq (line 195) | func GetIdRangeFromListReq(ctx context.Context) (exists bool, ids []int6...
  constant ResponseCodeKey (line 206) | ResponseCodeKey = "response_code"
  constant RawErrorKey (line 207) | RawErrorKey     = "raw_error"
  type ctxBind (line 210) | type ctxBind struct
    method withResponseCode (line 219) | func (cb *ctxBind) withResponseCode(code int) *ctxBind {
    method withRawError (line 225) | func (cb *ctxBind) withRawError(err error) *ctxBind {
  function contextBind (line 214) | func contextBind(c *gin.Context) *ctxBind {
  function GetResponseCode (line 231) | func GetResponseCode(ctx context.Context) (code int) {
  function GetRawError (line 242) | func GetRawError(ctx context.Context) (err error) {

FILE: api/server/httputils/httputils_test.go
  function Test_getObjectFromRequest (line 21) | func Test_getObjectFromRequest(t *testing.T) {

FILE: api/server/middleware/admission.go
  function Admission (line 22) | func Admission() gin.HandlerFunc {

FILE: api/server/middleware/audit.go
  constant defaultAuditQueueSize (line 37) | defaultAuditQueueSize = 2048
  constant defaultAuditWorkers (line 38) | defaultAuditWorkers   = 2
  constant auditWriteTimeout (line 39) | auditWriteTimeout     = 3 * time.Second
  type auditRecorder (line 42) | type auditRecorder struct
    method run (line 65) | func (r *auditRecorder) run() {
    method write (line 71) | func (r *auditRecorder) write(record *model.Audit) {
    method enqueue (line 80) | func (r *auditRecorder) enqueue(record *model.Audit) {
  function getAuditRecorder (line 52) | func getAuditRecorder(o *options.Options) *auditRecorder {
  function Audit (line 90) | func Audit(o *options.Options) gin.HandlerFunc {
  function buildAuditRecord (line 104) | func buildAuditRecord(c *gin.Context, startTime time.Time) *model.Audit {
  function parseK8sProxyPath (line 133) | func parseK8sProxyPath(path string) (cluster, resourceName, resourceName...
  function shouldAudit (line 169) | func shouldAudit(c *gin.Context) bool {
  function detectObjectType (line 176) | func detectObjectType(c *gin.Context) model.ObjectType {
  function getAuditStatus (line 189) | func getAuditStatus(c *gin.Context) model.AuditOperationStatus {
  function responseOK (line 205) | func responseOK(code int) bool {

FILE: api/server/middleware/authentication.go
  function Authentication (line 33) | func Authentication(o *options.Options) gin.HandlerFunc {
  function validate (line 60) | func validate(c *gin.Context, o *options.Options, keyBytes []byte) error {
  function extractToken (line 91) | func extractToken(c *gin.Context, ws bool) (string, error) {

FILE: api/server/middleware/authorization.go
  function Authorization (line 43) | func Authorization(o *options.Options) gin.HandlerFunc {

FILE: api/server/middleware/cors.go
  function Cors (line 26) | func Cors() gin.HandlerFunc {

FILE: api/server/middleware/limiter.go
  constant capacity (line 33) | capacity = 100
  constant quantum (line 34) | quantum  = 20
  constant cap (line 35) | cap      = 200
  function UserRateLimiter (line 40) | func UserRateLimiter() gin.HandlerFunc {
  function Limiter (line 63) | func Limiter() gin.HandlerFunc {

FILE: api/server/middleware/log.go
  function Logger (line 28) | func Logger(cfg *logutil.LogOptions) gin.HandlerFunc {

FILE: api/server/middleware/middleware.go
  function init (line 30) | func init() {
  function allowCustomRequest (line 35) | func allowCustomRequest(c *gin.Context) bool {
  function InstallMiddlewares (line 40) | func InstallMiddlewares(o *options.Options) {

FILE: api/server/router/audit/audit.go
  type auditRouter (line 26) | type auditRouter struct
    method initRoutes (line 37) | func (a *auditRouter) initRoutes(httpEngine *gin.Engine) {
  function NewRouter (line 30) | func NewRouter(o *options.Options) {

FILE: api/server/router/audit/audit_routes.go
  type AuditMeta (line 26) | type AuditMeta struct
  method getAudit (line 30) | func (a *auditRouter) getAudit(c *gin.Context) {
  method listAudits (line 49) | func (a *auditRouter) listAudits(c *gin.Context) {

FILE: api/server/router/auth/auth.go
  constant AuthBasePath (line 27) | AuthBasePath   = "/pixiu/auth"
  constant PolicySubPath (line 28) | PolicySubPath  = "/policy"
  constant BindingSubPath (line 29) | BindingSubPath = "/binding"
  type authRouter (line 32) | type authRouter struct
    method initRoutes (line 43) | func (a *authRouter) initRoutes(ge *gin.Engine) {
  function NewRouter (line 36) | func NewRouter(o *options.Options) {

FILE: api/server/router/auth/auth_routes.go
  type IdMeta (line 26) | type IdMeta struct
  method listPolicies (line 30) | func (a *authRouter) listPolicies(c *gin.Context) {
  method createPolicy (line 48) | func (a *authRouter) createPolicy(c *gin.Context) {
  method deletePolicy (line 63) | func (a *authRouter) deletePolicy(c *gin.Context) {
  method listBindings (line 78) | func (a *authRouter) listBindings(c *gin.Context) {
  method createBinding (line 96) | func (a *authRouter) createBinding(c *gin.Context) {
  method deleteBinding (line 111) | func (a *authRouter) deleteBinding(c *gin.Context) {

FILE: api/server/router/cluster/cluster.go
  constant kubeProxyBaseURL (line 27) | kubeProxyBaseURL = "/pixiu/kubeproxy"
  constant helmBaseURL (line 28) | helmBaseURL      = "/pixiu/helms"
  constant indexerBaseURL (line 29) | indexerBaseURL   = "/pixiu/indexer"
  type clusterRouter (line 33) | type clusterRouter struct
    method initRoutes (line 45) | func (cr *clusterRouter) initRoutes(httpEngine *gin.Engine) {
  function NewRouter (line 38) | func NewRouter(o *options.Options) {

FILE: api/server/router/cluster/cluster_routes.go
  type IdMeta (line 26) | type IdMeta struct
  method createCluster (line 44) | func (cr *clusterRouter) createCluster(c *gin.Context) {
  method updateCluster (line 75) | func (cr *clusterRouter) updateCluster(c *gin.Context) {
  method deleteCluster (line 114) | func (cr *clusterRouter) deleteCluster(c *gin.Context) {
  method getCluster (line 147) | func (cr *clusterRouter) getCluster(c *gin.Context) {
  method listClusters (line 183) | func (cr *clusterRouter) listClusters(c *gin.Context) {
  method pingCluster (line 215) | func (cr *clusterRouter) pingCluster(c *gin.Context) {
  method protectCluster (line 234) | func (cr *clusterRouter) protectCluster(c *gin.Context) {
  method aggregateEvents (line 253) | func (cr *clusterRouter) aggregateEvents(c *gin.Context) {
  method getEventList (line 277) | func (cr *clusterRouter) getEventList(c *gin.Context) {
  method watchPodLog (line 298) | func (cr *clusterRouter) watchPodLog(c *gin.Context) {

FILE: api/server/router/cluster/helper.go
  function IsKubeProxyPath (line 25) | func IsKubeProxyPath(c *gin.Context) bool {
  function IsHelmPath (line 29) | func IsHelmPath(c *gin.Context) bool {

FILE: api/server/router/cluster/informer.go
  type ResourceMeta (line 26) | type ResourceMeta struct
  method getIndexerResource (line 33) | func (cr *clusterRouter) getIndexerResource(c *gin.Context) {
  method listIndexerResources (line 52) | func (cr *clusterRouter) listIndexerResources(c *gin.Context) {

FILE: api/server/router/cluster/proxy.go
  type Action (line 26) | type Action struct
  method ReRunJob (line 31) | func (cr *clusterRouter) ReRunJob(c *gin.Context) {

FILE: api/server/router/cluster/ws.go
  method webShell (line 26) | func (cr *clusterRouter) webShell(c *gin.Context) {
  method nodeWebShell (line 42) | func (cr *clusterRouter) nodeWebShell(c *gin.Context) {

FILE: api/server/router/helm/helm.go
  constant helmBaseURL (line 27) | helmBaseURL = "/pixiu/helms"
  type helmRouter (line 30) | type helmRouter struct
    method initRoutes (line 41) | func (hr *helmRouter) initRoutes(httpEngine *gin.Engine) {
  function NewRouter (line 34) | func NewRouter(o *options.Options) {

FILE: api/server/router/helm/release_routes.go
  method GetRelease (line 41) | func (hr *helmRouter) GetRelease(c *gin.Context) {
  method ListReleases (line 73) | func (hr *helmRouter) ListReleases(c *gin.Context) {
  method InstallRelease (line 106) | func (hr *helmRouter) InstallRelease(c *gin.Context) {
  method UninstallRelease (line 141) | func (hr *helmRouter) UninstallRelease(c *gin.Context) {
  method UpgradeRelease (line 175) | func (hr *helmRouter) UpgradeRelease(c *gin.Context) {
  method GetReleaseHistory (line 210) | func (hr *helmRouter) GetReleaseHistory(c *gin.Context) {
  method RollbackRelease (line 245) | func (hr *helmRouter) RollbackRelease(c *gin.Context) {

FILE: api/server/router/helm/respository_routes.go
  method createRepository (line 39) | func (hr *helmRouter) createRepository(c *gin.Context) {
  method deleteRepository (line 72) | func (hr *helmRouter) deleteRepository(c *gin.Context) {
  method updateRepository (line 104) | func (hr *helmRouter) updateRepository(c *gin.Context) {
  method getRepository (line 137) | func (hr *helmRouter) getRepository(c *gin.Context) {
  method listRepositories (line 167) | func (hr *helmRouter) listRepositories(c *gin.Context) {
  method getRepoCharts (line 192) | func (hr *helmRouter) getRepoCharts(c *gin.Context) {
  method getRepoChartsByURL (line 224) | func (hr *helmRouter) getRepoChartsByURL(c *gin.Context) {
  method getChartValues (line 257) | func (hr *helmRouter) getChartValues(c *gin.Context) {

FILE: api/server/router/plan/config_routes.go
  type planConfigMeta (line 26) | type planConfigMeta struct
  method createPlanConfig (line 32) | func (t *planRouter) createPlanConfig(c *gin.Context) {
  method updatePlanConfig (line 52) | func (t *planRouter) updatePlanConfig(c *gin.Context) {
  method deletePlanConfig (line 72) | func (t *planRouter) deletePlanConfig(c *gin.Context) {
  method getPlanConfig (line 91) | func (t *planRouter) getPlanConfig(c *gin.Context) {

FILE: api/server/router/plan/node_routes.go
  type planNodeMeta (line 26) | type planNodeMeta struct
  method createPlanNode (line 32) | func (t *planRouter) createPlanNode(c *gin.Context) {
  method updatePlanNode (line 52) | func (t *planRouter) updatePlanNode(c *gin.Context) {
  method deletePlanNode (line 72) | func (t *planRouter) deletePlanNode(c *gin.Context) {
  method getPlanNode (line 91) | func (t *planRouter) getPlanNode(c *gin.Context) {
  method listPlanNodes (line 110) | func (t *planRouter) listPlanNodes(c *gin.Context) {

FILE: api/server/router/plan/plan.go
  type planRouter (line 26) | type planRouter struct
    method initRoutes (line 37) | func (t *planRouter) initRoutes(ginEngine *gin.Engine) {
  function NewRouter (line 30) | func NewRouter(o *options.Options) {

FILE: api/server/router/plan/plan_routes.go
  type planMeta (line 26) | type planMeta struct
  type watchTaskLogMeta (line 30) | type watchTaskLogMeta struct
  type WatchMeta (line 35) | type WatchMeta struct
  method createPlan (line 40) | func (t *planRouter) createPlan(c *gin.Context) {
  method updatePlan (line 56) | func (t *planRouter) updatePlan(c *gin.Context) {
  method deletePlan (line 76) | func (t *planRouter) deletePlan(c *gin.Context) {
  method getPlan (line 95) | func (t *planRouter) getPlan(c *gin.Context) {
  method getPlanWithSubResources (line 118) | func (t *planRouter) getPlanWithSubResources(c *gin.Context) {
  method listPlans (line 137) | func (t *planRouter) listPlans(c *gin.Context) {
  method startPlan (line 156) | func (t *planRouter) startPlan(c *gin.Context) {
  method stopPlan (line 175) | func (t *planRouter) stopPlan(c *gin.Context) {
  type DistributionsMeta (line 194) | type DistributionsMeta struct
  method getDistributions (line 202) | func (t *planRouter) getDistributions(c *gin.Context) {

FILE: api/server/router/plan/task_routes.go
  type taskNodeMeta (line 25) | type taskNodeMeta struct
  method runTasks (line 31) | func (t *planRouter) runTasks(c *gin.Context) {
  method listTasks (line 37) | func (t *planRouter) listTasks(c *gin.Context) {
  method watchTaskLog (line 64) | func (t *planRouter) watchTaskLog(c *gin.Context) {

FILE: api/server/router/proxy/helper.go
  function IsProxyPath (line 26) | func IsProxyPath(c *gin.Context) bool {

FILE: api/server/router/proxy/proxy.go
  constant proxyBaseURL (line 34) | proxyBaseURL = "/pixiu/proxy"
  type proxyRouter (line 37) | type proxyRouter struct
    method initRoutes (line 48) | func (p *proxyRouter) initRoutes(ginEngine *gin.Engine) {
    method proxyHandler (line 55) | func (p *proxyRouter) proxyHandler(c *gin.Context) {
    method parseTarget (line 89) | func (p *proxyRouter) parseTarget(target url.URL, host string, name st...
  function NewRouter (line 41) | func NewRouter(o *options.Options) {

FILE: api/server/router/router.go
  type RegisterFunc (line 44) | type RegisterFunc
  function InstallRouters (line 49) | func InstallRouters(o *options.Options) {
  function install (line 73) | func install(o *options.Options, fs ...RegisterFunc) {

FILE: api/server/router/tenant/tenant.go
  type tenantRouter (line 26) | type tenantRouter struct
    method initRoutes (line 37) | func (t *tenantRouter) initRoutes(ginEngine *gin.Engine) {
  function NewRouter (line 30) | func NewRouter(o *options.Options) {

FILE: api/server/router/tenant/tenant_routes.go
  type TenantMeta (line 26) | type TenantMeta struct
  method createTenant (line 30) | func (t *tenantRouter) createTenant(c *gin.Context) {
  method updateTenant (line 46) | func (t *tenantRouter) updateTenant(c *gin.Context) {
  method deleteTenant (line 70) | func (t *tenantRouter) deleteTenant(c *gin.Context) {
  method getTenant (line 89) | func (t *tenantRouter) getTenant(c *gin.Context) {
  method listTenants (line 108) | func (t *tenantRouter) listTenants(c *gin.Context) {

FILE: api/server/router/user/user.go
  type userRouter (line 26) | type userRouter struct
    method initRoutes (line 37) | func (u *userRouter) initRoutes(httpEngine *gin.Engine) {
  function NewRouter (line 30) | func NewRouter(o *options.Options) {

FILE: api/server/router/user/user_routes.go
  type IdMeta (line 26) | type IdMeta struct
  method createUser (line 44) | func (u *userRouter) createUser(c *gin.Context) {
  method updateUser (line 78) | func (u *userRouter) updateUser(c *gin.Context) {
  method updatePassword (line 113) | func (u *userRouter) updatePassword(c *gin.Context) {
  method deleteUser (line 147) | func (u *userRouter) deleteUser(c *gin.Context) {
  method getUser (line 180) | func (u *userRouter) getUser(c *gin.Context) {
  method listUsers (line 212) | func (u *userRouter) listUsers(c *gin.Context) {
  method login (line 243) | func (u *userRouter) login(c *gin.Context) {
  method logout (line 266) | func (u *userRouter) logout(c *gin.Context) {

FILE: api/server/validator/helper.go
  function TranslateError (line 26) | func TranslateError(errs validator.ValidationErrors) string {

FILE: api/server/validator/password.go
  function init (line 25) | func init() {
  type passwordValidator (line 32) | type passwordValidator struct
    method validate (line 37) | func (pv *passwordValidator) validate(fl validator.FieldLevel) bool {

FILE: api/server/validator/rbac.go
  function init (line 26) | func init() {
  type objectValidator (line 34) | type objectValidator struct
    method validate (line 38) | func (ov *objectValidator) validate(fl validator.FieldLevel) bool {
  type operationValidator (line 44) | type operationValidator struct
    method validate (line 48) | func (ov *operationValidator) validate(fl validator.FieldLevel) bool {
  type stringIDValidator (line 54) | type stringIDValidator struct
    method validate (line 58) | func (sv *stringIDValidator) validate(fl validator.FieldLevel) bool {

FILE: api/server/validator/validator.go
  type customValidator (line 27) | type customValidator interface
  function register (line 40) | func register(validators ...customValidator) {
  function init (line 44) | func init() {
  type pixiuValidator (line 59) | type pixiuValidator struct
    method getTag (line 71) | func (c pixiuValidator) getTag() string {
    method translateError (line 75) | func (c pixiuValidator) translateError(ut ut.Translator) error {
    method translate (line 79) | func (c pixiuValidator) translate(ut ut.Translator, fe validator.Field...
  function newPixiuValidator (line 64) | func newPixiuValidator(tag, err string) pixiuValidator {

FILE: cmd/app/config/config.go
  type Mode (line 26) | type Mode
    method InDebug (line 33) | func (m Mode) InDebug() bool {
  constant DebugMode (line 29) | DebugMode   Mode = "debug"
  constant ReleaseMode (line 30) | ReleaseMode Mode = "release"
  type Config (line 37) | type Config struct
    method Valid (line 117) | func (c *Config) Valid() (err error) {
  type DefaultOptions (line 45) | type DefaultOptions struct
    method Valid (line 62) | func (o DefaultOptions) Valid() error {
  type MysqlOptions (line 70) | type MysqlOptions struct
    method Valid (line 78) | func (o MysqlOptions) Valid() error {
  type WorkerOptions (line 83) | type WorkerOptions struct
    method Valid (line 93) | func (w WorkerOptions) Valid() error {
  type Engine (line 88) | type Engine struct
  type TLS (line 98) | type TLS struct
    method Valid (line 103) | func (t *TLS) Valid() error {

FILE: cmd/app/options/options.go
  constant maxIdleConns (line 46) | maxIdleConns = 10
  constant maxOpenConns (line 47) | maxOpenConns = 100
  constant defaultListen (line 49) | defaultListen     = 8080
  constant defaultTokenKey (line 50) | defaultTokenKey   = "pixiu"
  constant defaultConfigFile (line 51) | defaultConfigFile = "/etc/pixiu/config.yaml"
  constant defaultLogFormat (line 52) | defaultLogFormat  = logutil.LogFormatJson
  constant defaultWorkDir (line 53) | defaultWorkDir    = "/etc/pixiu"
  constant defaultStaticDir (line 54) | defaultStaticDir  = "/static"
  constant defaultAdminUser (line 56) | defaultAdminUser     = "admin"
  constant defaultAdminPassword (line 57) | defaultAdminPassword = "Pixiu123456!"
  constant defaultSlowSQLDuration (line 59) | defaultSlowSQLDuration = 1 * time.Second
  constant rulesTableName (line 61) | rulesTableName = "rules"
  type Options (line 65) | type Options struct
    method Complete (line 93) | func (o *Options) Complete() error {
    method BindFlags (line 166) | func (o *Options) BindFlags(cmd *cobra.Command) {
    method register (line 170) | func (o *Options) register() error {
    method registerEnforcer (line 185) | func (o *Options) registerEnforcer() error {
    method registerDatabase (line 206) | func (o *Options) registerDatabase() error {
    method Validate (line 237) | func (o *Options) Validate() error {
    method bootstrapRootUser (line 245) | func (o *Options) bootstrapRootUser() error {
  function NewOptions (line 85) | func NewOptions() (*Options, error) {

FILE: cmd/app/server.go
  function NewServerCommand (line 35) | func NewServerCommand(version string) *cobra.Command {
  function Run (line 84) | func Run(opt *options.Options) error {

FILE: cmd/pixiuserver.go
  function main (line 51) | func main() {

FILE: hack/tools/licfmt/licfmt.go
  constant tpml (line 35) | tpml = `/*
  function init (line 58) | func init() {
  type stringSlice (line 62) | type stringSlice
    method String (line 64) | func (i *stringSlice) String() string {
    method Set (line 68) | func (i *stringSlice) Set(value string) error {
  type file (line 73) | type file struct
  function main (line 78) | func main() {
  function walk (line 129) | func walk(ch chan<- *file, root string) error {
  function match (line 149) | func match(path string, patterns []string) bool {
  function hasLicense (line 159) | func hasLicense(header []byte) bool {
  function notAlowEditd (line 164) | func notAlowEditd(header []byte) bool {
  function addLicenseHeader (line 170) | func addLicenseHeader(path, license string, fmode os.FileMode) (bool, er...
  function scanLines (line 232) | func scanLines(file *os.File) (buf bytes.Buffer, dropped int64) {

FILE: pkg/client/cache.go
  type PixiuInformer (line 46) | type PixiuInformer struct
    method NodesLister (line 51) | func (p PixiuInformer) NodesLister() v1.NodeLister {
    method PodsLister (line 55) | func (p PixiuInformer) PodsLister() v1.PodLister {
    method NamespacesLister (line 59) | func (p PixiuInformer) NamespacesLister() v1.NamespaceLister {
    method DeploymentsLister (line 63) | func (p PixiuInformer) DeploymentsLister() appsv1.DeploymentLister {
    method StatefulSetsLister (line 67) | func (p *PixiuInformer) StatefulSetsLister() appsv1.StatefulSetLister {
    method DaemonSetsLister (line 71) | func (p *PixiuInformer) DaemonSetsLister() appsv1.DaemonSetLister {
    method CronJobsLister (line 75) | func (p *PixiuInformer) CronJobsLister() batchv1.CronJobLister {
    method JobsLister (line 79) | func (p *PixiuInformer) JobsLister() batchv1.JobLister { return p.Shar...
  type ClusterSet (line 81) | type ClusterSet struct
    method Complete (line 88) | func (cs *ClusterSet) Complete(cfg []byte) error {
  function NewSharedInformers (line 111) | func NewSharedInformers(c *restclient.Config) (informers.SharedInformerF...
  type store (line 133) | type store
  type Cache (line 135) | type Cache struct
    method Get (line 146) | func (s *Cache) Get(name string) (ClusterSet, bool) {
    method GetConfig (line 154) | func (s *Cache) GetConfig(name string) (*restclient.Config, bool) {
    method GetClient (line 165) | func (s *Cache) GetClient(name string) (*kubernetes.Clientset, bool) {
    method Set (line 177) | func (s *Cache) Set(name string, cs ClusterSet) {
    method Delete (line 187) | func (s *Cache) Delete(name string) {
    method List (line 202) | func (s *Cache) List() store {
    method Clear (line 209) | func (s *Cache) Clear() {
  function NewClusterCache (line 140) | func NewClusterCache() *Cache {

FILE: pkg/client/client.go
  function ParseKubeConfigBytes (line 26) | func ParseKubeConfigBytes(cfg string) ([]byte, error) {
  function NewClientSetFromBytes (line 35) | func NewClientSetFromBytes(data []byte) (*kubernetes.Clientset, error) {
  function NewClientSetFromString (line 44) | func NewClientSetFromString(cfg string) (*kubernetes.Clientset, error) {
  function NewClusterSet (line 53) | func NewClusterSet(cfg string) (*ClusterSet, error) {

FILE: pkg/client/helm.go
  type HelmRESTClientGetter (line 29) | type HelmRESTClientGetter struct
    method ToDiscoveryClient (line 36) | func (h *HelmRESTClientGetter) ToDiscoveryClient() (discovery.CachedDi...
    method ToRESTConfig (line 46) | func (h *HelmRESTClientGetter) ToRESTConfig() (*rest.Config, error) {
    method ToRESTMapper (line 51) | func (h *HelmRESTClientGetter) ToRESTMapper() (meta.RESTMapper, error) {
    method ToRawKubeConfigLoader (line 62) | func (h *HelmRESTClientGetter) ToRawKubeConfigLoader() clientcmd.Clien...
  function NewHelmRESTClientGetter (line 69) | func NewHelmRESTClientGetter(kubeConfig *rest.Config) *HelmRESTClientGet...

FILE: pkg/client/task.go
  type WrapObject (line 29) | type WrapObject struct
  type Task (line 34) | type Task struct
    method SetLister (line 48) | func (t *Task) SetLister(Lister func(ctx context.Context, planId int64...
    method Get (line 55) | func (t *Task) Get(planId int64) ([]model.Task, bool) {
    method Set (line 69) | func (t *Task) Set(planId int64, tasks []model.Task) {
    method SetByTask (line 85) | func (t *Task) SetByTask(planId int64, task model.Task) {
    method Delete (line 115) | func (t *Task) Delete(planId int64) {
    method WaitForCacheSync (line 124) | func (t *Task) WaitForCacheSync(planId int64) error {
    method syncTasks (line 139) | func (t *Task) syncTasks() {
    method Run (line 173) | func (t *Task) Run() {
  function NewTaskCache (line 41) | func NewTaskCache() *Task {

FILE: pkg/client/token_cache.go
  type TokenCache (line 23) | type TokenCache struct
    method Get (line 34) | func (s *TokenCache) Get(uid int64) (string, bool) {
    method Set (line 42) | func (s *TokenCache) Set(uid int64, token string) {
    method Delete (line 52) | func (s *TokenCache) Delete(uid int64) {
    method Clear (line 59) | func (s *TokenCache) Clear() {
  function NewTokenCache (line 28) | func NewTokenCache() *TokenCache {

FILE: pkg/client/user_cache.go
  type UserCache (line 21) | type UserCache struct
    method Get (line 32) | func (s *UserCache) Get(uid int64) (int, bool) {
    method Set (line 40) | func (s *UserCache) Set(uid int64, status int) {
    method Delete (line 50) | func (s *UserCache) Delete(uid int64) {
    method Clear (line 57) | func (s *UserCache) Clear() {
  function NewUserCache (line 26) | func NewUserCache() *UserCache {

FILE: pkg/controller/audit/audit.go
  type AuditGetter (line 32) | type AuditGetter interface
  type Interface (line 36) | type Interface interface
  type audit (line 41) | type audit struct
    method Get (line 46) | func (a *audit) Get(ctx context.Context, aid int64) (*types.Audit, err...
    method List (line 58) | func (a *audit) List(ctx context.Context, listOption types.AuditListOp...
    method model2Type (line 131) | func (a *audit) model2Type(o *model.Audit) *types.Audit {
  function buildAuditFilterOpts (line 101) | func buildAuditFilterOpts(opt types.AuditListOptions) []db.Options {
  function NewAudit (line 155) | func NewAudit(cfg config.Config, f db.ShareDaoFactory) *audit {

FILE: pkg/controller/auth/auth.go
  type AuthGetter (line 34) | type AuthGetter interface
  type Interface (line 39) | type Interface interface
  type auth (line 50) | type auth struct
    method getPolicy (line 63) | func (a *auth) getPolicy(ctx context.Context, req *types.RBACPolicyReq...
    method getBinding (line 81) | func (a *auth) getBinding(ctx context.Context, req *types.GroupBinding...
    method CreateRBACPolicy (line 103) | func (a *auth) CreateRBACPolicy(ctx context.Context, req *types.RBACPo...
    method DeleteRBACPolicy (line 121) | func (a *auth) DeleteRBACPolicy(ctx context.Context, req *types.RBACPo...
    method ListRBACPolicies (line 155) | func (a *auth) ListRBACPolicies(ctx context.Context, req *types.ListRB...
    method CreateGroupBinding (line 189) | func (a *auth) CreateGroupBinding(ctx context.Context, req *types.Grou...
    method DeleteGroupBinding (line 207) | func (a *auth) DeleteGroupBinding(ctx context.Context, req *types.Grou...
    method ListGroupBindings (line 225) | func (a *auth) ListGroupBindings(ctx context.Context, req *types.ListG...
  function NewAuth (line 55) | func NewAuth(factory db.ShareDaoFactory, enforcer *casbin.SyncedEnforcer...
  function model2Type (line 265) | func model2Type(policy model.Policy) *types.RBACPolicy {

FILE: pkg/controller/cluster/cluster.go
  type ClusterGetter (line 56) | type ClusterGetter interface
  type Interface (line 60) | type Interface interface
  function init (line 99) | func init() {
  type listerFunc (line 104) | type listerFunc
  type getterFunc (line 105) | type getterFunc
  type InformerResource (line 108) | type InformerResource struct
  type cluster (line 115) | type cluster struct
    method preCreate (line 124) | func (c *cluster) preCreate(ctx context.Context, req *types.CreateClus...
    method Create (line 132) | func (c *cluster) Create(ctx context.Context, req *types.CreateCluster...
    method Update (line 178) | func (c *cluster) Update(ctx context.Context, cid int64, req *types.Up...
    method preDelete (line 206) | func (c *cluster) preDelete(ctx context.Context, cid int64) (cluster *...
    method Delete (line 224) | func (c *cluster) Delete(ctx context.Context, cid int64) error {
    method Get (line 249) | func (c *cluster) Get(ctx context.Context, cid int64) (*types.Cluster,...
    method List (line 261) | func (c *cluster) List(ctx context.Context, req *types.ListClusterRequ...
    method Ping (line 304) | func (c *cluster) Ping(ctx context.Context, kubeConfig string) error {
    method Protect (line 323) | func (c *cluster) Protect(ctx context.Context, cid int64, req *types.P...
    method GetEventList (line 334) | func (c *cluster) GetEventList(ctx context.Context, cluster string, op...
    method WatchPodLog (line 366) | func (c *cluster) WatchPodLog(ctx context.Context, cluster string, nam...
    method ReRunJob (line 419) | func (c *cluster) ReRunJob(ctx context.Context, cluster string, namesp...
    method AggregateEvents (line 470) | func (c *cluster) AggregateEvents(ctx context.Context, cluster string,...
    method GetKubeObjectByLabel (line 571) | func (c *cluster) GetKubeObjectByLabel(Client *kubernetes.Clientset, n...
    method GetKubeConfigByName (line 616) | func (c *cluster) GetKubeConfigByName(ctx context.Context, name string...
    method GetClusterSetByName (line 626) | func (c *cluster) GetClusterSetByName(ctx context.Context, name string...
    method GetKubernetesMeta (line 654) | func (c *cluster) GetKubernetesMeta(ctx context.Context, clusterName s...
    method GetKubernetesMetaFromPlan (line 688) | func (c *cluster) GetKubernetesMetaFromPlan(ctx context.Context, planI...
    method makeFieldSelector (line 710) | func (c *cluster) makeFieldSelector(uid apitypes.UID, name string, nam...
    method parseKubernetesResource (line 729) | func (c *cluster) parseKubernetesResource(nodeMetrics []v1beta1.NodeMe...
    method model2Type (line 782) | func (c *cluster) model2Type(o *model.Cluster) *types.Cluster {
    method GetClusterStatusFromPlanTask (line 837) | func (c *cluster) GetClusterStatusFromPlanTask(planId int64) (model.Cl...
    method registerIndexers (line 862) | func (c *cluster) registerIndexers(informerResources ...InformerResour...
    method Run (line 869) | func (c *cluster) Run(ctx context.Context, workers int) error {
    method Sync (line 877) | func (c *cluster) Sync(ctx context.Context) {
  constant Retries (line 416) | Retries = 3
  function parseFloat64FromString (line 768) | func parseFloat64FromString(s string) float64 {
  function NewCluster (line 881) | func NewCluster(cfg config.Config, f db.ShareDaoFactory, e *casbin.Synce...

FILE: pkg/controller/cluster/informer.go
  constant ResourceNode (line 34) | ResourceNode        = "node"
  constant ResourcePod (line 35) | ResourcePod         = "pod"
  constant ResourceDeployment (line 36) | ResourceDeployment  = "deployment"
  constant ResourceStatefulSet (line 37) | ResourceStatefulSet = "statefulset"
  constant ResourceDaemonSet (line 38) | ResourceDaemonSet   = "daemonset"
  constant ResourceCronJob (line 39) | ResourceCronJob     = "cronjob"
  constant ResourceJob (line 40) | ResourceJob         = "job"
  method GetIndexerResource (line 43) | func (c *cluster) GetIndexerResource(ctx context.Context, cluster string...
  method GetPod (line 60) | func (c *cluster) GetPod(ctx context.Context, podsLister v1.PodLister, n...
  method GetDeployment (line 70) | func (c *cluster) GetDeployment(ctx context.Context, deploymentsLister l...
  method GetStatefulSet (line 80) | func (c *cluster) GetStatefulSet(ctx context.Context, statefulSetsLister...
  method GetDaemonSet (line 90) | func (c *cluster) GetDaemonSet(ctx context.Context, daemonSetsLister lis...
  method GetCronJob (line 100) | func (c *cluster) GetCronJob(ctx context.Context, cronJobsLister listers...
  method GetJob (line 110) | func (c *cluster) GetJob(ctx context.Context, cronJobsLister listersbatc...
  method GetNode (line 120) | func (c *cluster) GetNode(ctx context.Context, nodesLister v1.NodeLister...
  method ListIndexerResources (line 130) | func (c *cluster) ListIndexerResources(ctx context.Context, cluster stri...
  method ListPods (line 149) | func (c *cluster) ListPods(ctx context.Context, podsLister v1.PodLister,...
  method ListDeployments (line 164) | func (c *cluster) ListDeployments(ctx context.Context, deploymentsLister...
  method ListStatefulSets (line 177) | func (c *cluster) ListStatefulSets(ctx context.Context, statefulSetsList...
  method ListDaemonSets (line 190) | func (c *cluster) ListDaemonSets(ctx context.Context, daemonSetsLister l...
  method ListCronJobs (line 203) | func (c *cluster) ListCronJobs(ctx context.Context, cronJobsLister liste...
  method ListJobs (line 216) | func (c *cluster) ListJobs(ctx context.Context, jobsLister listersbatchv...
  method ListNodes (line 229) | func (c *cluster) ListNodes(ctx context.Context, nodesLister v1.NodeList...

FILE: pkg/controller/cluster/util.go
  method forQuery (line 28) | func (c *cluster) forQuery(objects []metav1.Object, queryOption types.Qu...
  method forPage (line 46) | func (c *cluster) forPage(objects []metav1.Object, pageOption types.Page...
  method forSorted (line 58) | func (c *cluster) forSorted(objects []metav1.Object, namespace string) [...
  method listObjects (line 72) | func (c *cluster) listObjects(objects []metav1.Object, namespace string,...

FILE: pkg/controller/cluster/ws.go
  method WsHandler (line 37) | func (c *cluster) WsHandler(ctx context.Context, opt *types.WebShellOpti...
  method WsNodeHandler (line 97) | func (c *cluster) WsNodeHandler(ctx context.Context, sshConfig *types.We...
  function handler (line 131) | func handler(turn *types.Turn) {

FILE: pkg/controller/controller.go
  type PixiuInterface (line 33) | type PixiuInterface interface
  type pixiu (line 43) | type pixiu struct
    method Cluster (line 49) | func (p *pixiu) Cluster() cluster.Interface { return cluster.NewCluste...
    method Tenant (line 50) | func (p *pixiu) Tenant() tenant.Interface   { return tenant.NewTenant(...
    method User (line 51) | func (p *pixiu) User() user.Interface       { return user.NewUser(p.cc...
    method Plan (line 52) | func (p *pixiu) Plan() plan.Interface       { return plan.NewPlan(p.cc...
    method Audit (line 53) | func (p *pixiu) Audit() audit.Interface     { return audit.NewAudit(p....
    method Auth (line 54) | func (p *pixiu) Auth() auth.Interface       { return auth.NewAuth(p.fa...
    method Helm (line 55) | func (p *pixiu) Helm() helm.Interface       { return helm.NewHelm(p.fa...
  function New (line 57) | func New(cfg config.Config, f db.ShareDaoFactory, enforcer *casbin.Synce...

FILE: pkg/controller/helm/helm.go
  type HelmGetter (line 31) | type HelmGetter interface
  type Interface (line 35) | type Interface interface
  type Helm (line 40) | type Helm struct
    method Release (line 44) | func (h *Helm) Release(cluster, namespace string) ReleaseInterface {
    method Repository (line 59) | func (h *Helm) Repository() RepositoryInterface {
    method MustGetClusterSetByName (line 69) | func (h *Helm) MustGetClusterSetByName(ctx context.Context, name strin...
  function NewHelm (line 63) | func NewHelm(factory db.ShareDaoFactory) Interface {

FILE: pkg/controller/helm/releases.go
  type ReleaseInterface (line 37) | type ReleaseInterface interface
  type Releases (line 48) | type Releases struct
    method Get (line 62) | func (r *Releases) Get(ctx context.Context, name string) (*release.Rel...
    method List (line 67) | func (r *Releases) List(ctx context.Context) ([]*release.Release, erro...
    method Install (line 73) | func (r *Releases) Install(ctx context.Context, form *types.Release) (...
    method Uninstall (line 94) | func (r *Releases) Uninstall(ctx context.Context, name string) (*relea...
    method Upgrade (line 100) | func (r *Releases) Upgrade(ctx context.Context, form *types.Release) (...
    method History (line 120) | func (r *Releases) History(ctx context.Context, name string) ([]*relea...
    method Rollback (line 125) | func (r *Releases) Rollback(ctx context.Context, name string, toVersio...
    method locateChart (line 137) | func (r *Releases) locateChart(pathOpts action.ChartPathOptions, chart...
  function NewReleases (line 53) | func NewReleases(actionConfig *action.Configuration, settings *cli.EnvSe...
  function checkIfInstallable (line 199) | func checkIfInstallable(ch *chart.Chart) error {

FILE: pkg/controller/helm/repository.go
  type RepositoryGetter (line 38) | type RepositoryGetter interface
  type RepositoryInterface (line 42) | type RepositoryInterface interface
  type Repository (line 54) | type Repository struct
    method Create (line 69) | func (r *Repository) Create(ctx context.Context, repo *types.CreateRep...
    method Delete (line 83) | func (r *Repository) Delete(ctx context.Context, id int64) error {
    method Get (line 87) | func (r *Repository) Get(ctx context.Context, id int64) (*model.Reposi...
    method GetByName (line 91) | func (r *Repository) GetByName(ctx context.Context, name string) (*mod...
    method List (line 95) | func (r *Repository) List(ctx context.Context) ([]*model.Repository, e...
    method Update (line 99) | func (r *Repository) Update(ctx context.Context, id int64, update *typ...
    method GetChartsById (line 109) | func (r *Repository) GetChartsById(ctx context.Context, id int64) (*mo...
    method GetChartsByURL (line 124) | func (r *Repository) GetChartsByURL(ctx context.Context, repoURL strin...
    method GetChartValues (line 131) | func (r *Repository) GetChartValues(_ context.Context, chart, version ...
    method resolveReferenceURL (line 147) | func (r *Repository) resolveReferenceURL(baseURL, refURL string) (stri...
    method fetch (line 170) | func (r *Repository) fetch(_ context.Context, entry *repo.Entry) (*mod...
  function NewRepository (line 60) | func NewRepository(f db.ShareDaoFactory) *Repository {

FILE: pkg/controller/plan/bootstrap_servers.go
  type BootStrap (line 26) | type BootStrap struct
    method Name (line 33) | func (b BootStrap) Name() string { return "初始化部署环境" }
    method Run (line 36) | func (b BootStrap) Run() error {

FILE: pkg/controller/plan/checker.go
  type Check (line 19) | type Check struct
    method Name (line 23) | func (c Check) Name() string { return "部署预检查" }
    method Run (line 24) | func (c Check) Run() error {

FILE: pkg/controller/plan/deploy.go
  type Deploy (line 27) | type Deploy struct
    method Name (line 34) | func (b Deploy) Name() string { return "部署Master" }
    method Run (line 37) | func (b Deploy) Run() error {
  type DeployNode (line 55) | type DeployNode struct
    method Name (line 59) | func (b DeployNode) Name() string { return "部署Node" }
    method Run (line 62) | func (b DeployNode) Run() error {
  type DeployChart (line 66) | type DeployChart struct
    method Name (line 70) | func (b DeployChart) Name() string         { return "部署基础组件" }
    method Step (line 71) | func (b DeployChart) Step() model.PlanStep { return model.CompletedPla...
    method Run (line 74) | func (b DeployChart) Run() error {

FILE: pkg/controller/plan/plan.go
  type PlanGetter (line 39) | type PlanGetter interface
  type Interface (line 43) | type Interface interface
  function init (line 80) | func init() {
  type plan (line 85) | type plan struct
    method Create (line 96) | func (p *plan) Create(ctx context.Context, req *types.CreatePlanReques...
    method createPlanSubResources (line 129) | func (p *plan) createPlanSubResources(ctx context.Context, req *types....
    method Update (line 165) | func (p *plan) Update(ctx context.Context, planId int64, req *types.Up...
    method preDelete (line 196) | func (p *plan) preDelete(ctx context.Context, planId int64) error {
    method Delete (line 212) | func (p *plan) Delete(ctx context.Context, planId int64) error {
    method Get (line 244) | func (p *plan) Get(ctx context.Context, pid int64) (*types.Plan, error) {
    method GetWithSubResources (line 258) | func (p *plan) GetWithSubResources(ctx context.Context, planId int64) ...
    method List (line 279) | func (p *plan) List(ctx context.Context, req *types.ListPlanRequest) (...
    method listAll (line 326) | func (p *plan) listAll(ctx context.Context) ([]types.Plan, error) {
    method SyncTaskStatus (line 344) | func (p *plan) SyncTaskStatus(ctx context.Context) error {
    method preStart (line 377) | func (p *plan) preStart(ctx context.Context, pid int64) error {
    method TaskIsRunning (line 415) | func (p *plan) TaskIsRunning(ctx context.Context, planId int64) (bool,...
    method Start (line 432) | func (p *plan) Start(ctx context.Context, pid int64) error {
    method Stop (line 442) | func (p *plan) Stop(ctx context.Context, pid int64) error {
    method model2Type (line 446) | func (p *plan) model2Type(o *model.Plan) (*types.Plan, error) {
  function NewPlan (line 498) | func NewPlan(cfg config.Config, f db.ShareDaoFactory) *plan {

FILE: pkg/controller/plan/plan_config.go
  method preCreateConfig (line 30) | func (p *plan) preCreateConfig(ctx context.Context, planId int64, req *t...
  method CreateConfig (line 39) | func (p *plan) CreateConfig(ctx context.Context, pid int64, req *types.C...
  method UpdateConfig (line 61) | func (p *plan) UpdateConfig(ctx context.Context, pid int64, cfgId int64,...
  method UpdateConfigIfNeeded (line 67) | func (p *plan) UpdateConfigIfNeeded(ctx context.Context, planId int64, r...
  method DeleteConfig (line 126) | func (p *plan) DeleteConfig(ctx context.Context, pid int64, cfgId int64)...
  method GetConfig (line 135) | func (p *plan) GetConfig(ctx context.Context, pid int64) (*types.PlanCon...
  method buildAndCleanKubernetesConfig (line 145) | func (p *plan) buildAndCleanKubernetesConfig(ks types.KubernetesSpec) (s...
  method buildPlanConfig (line 158) | func (p *plan) buildPlanConfig(ctx context.Context, req *types.CreatePla...
  method modelConfig2Type (line 186) | func (p *plan) modelConfig2Type(o *model.Config) (*types.PlanConfig, err...

FILE: pkg/controller/plan/plan_node.go
  method preCreateNode (line 33) | func (p *plan) preCreateNode(ctx context.Context, pid int64, req *types....
  method CreateNode (line 42) | func (p *plan) CreateNode(ctx context.Context, pid int64, req *types.Cre...
  method CreateNodes (line 53) | func (p *plan) CreateNodes(ctx context.Context, planId int64, nodes []ty...
  method UpdateNode (line 66) | func (p *plan) UpdateNode(ctx context.Context, pid int64, nodeId int64, ...
  method updateNodesIfNeeded (line 73) | func (p *plan) updateNodesIfNeeded(ctx context.Context, planId int64, re...
  method buildNodeFromRequest (line 114) | func (p *plan) buildNodeFromRequest(planId int64, req *types.CreatePlanN...
  method createNode (line 130) | func (p *plan) createNode(ctx context.Context, planId int64, req *types....
  method DeleteNode (line 144) | func (p *plan) DeleteNode(ctx context.Context, pid int64, nodeId int64) ...
  method GetNode (line 153) | func (p *plan) GetNode(ctx context.Context, pid int64, nodeId int64) (*t...
  method ListNodes (line 163) | func (p *plan) ListNodes(ctx context.Context, pid int64) ([]types.PlanNo...
  method CreateOrUpdateNode (line 183) | func (p *plan) CreateOrUpdateNode(ctx context.Context, object *model.Nod...
  method modelNode2Type (line 208) | func (p *plan) modelNode2Type(o *model.Node) (*types.PlanNode, error) {
  method buildNodeUpdates (line 231) | func (p *plan) buildNodeUpdates(old, object *model.Node) map[string]inte...

FILE: pkg/controller/plan/plan_task.go
  method RunTask (line 37) | func (p *plan) RunTask(ctx context.Context, planId int64, taskId int64) ...
  method ListTasks (line 41) | func (p *plan) ListTasks(ctx context.Context, planId int64) ([]types.Pla...
  method WatchTasks (line 56) | func (p *plan) WatchTasks(ctx context.Context, planId int64, w http.Resp...
  method WatchTaskLog (line 96) | func (p *plan) WatchTaskLog(ctx context.Context, planId int64, taskId in...
  method modelTask2Type (line 157) | func (p *plan) modelTask2Type(o *model.Task) *types.PlanTask {
  method modelTask2TypeList (line 174) | func (p *plan) modelTask2TypeList(o []*model.Task) []types.PlanTask {

FILE: pkg/controller/plan/register.go
  constant KubeConfigFile (line 38) | KubeConfigFile = "/etc/kubernetes/admin.conf"
  type Register (line 41) | type Register struct
    method Name (line 47) | func (c Register) Name() string { return "集群注册" }
    method Run (line 48) | func (c Register) Run() error {
  function getKubeConfigFromMasterNode (line 91) | func getKubeConfigFromMasterNode(maserNode model.Node) ([]byte, error) {
  function newSftpClient (line 112) | func newSftpClient(node model.Node) (*sftp.Client, error) {

FILE: pkg/controller/plan/render.go
  type Render (line 37) | type Render struct
    method Name (line 43) | func (r Render) Name() string { return "配置渲染" }
    method Run (line 44) | func (r Render) Run() error {
    method doRender (line 69) | func (r Render) doRender(name string, text string, data interface{}) e...
  type Multinode (line 88) | type Multinode struct
  function ParseMultinode (line 95) | func ParseMultinode(data TaskData, workDir string) (Multinode, error) {
  function GetRenderFile (line 159) | func GetRenderFile(planId int64, workDir string, f string) (string, erro...
  function RenderRSA (line 168) | func RenderRSA(planId int64, name string, workDir string, auth types.Pla...
  function GetRSAFile (line 186) | func GetRSAFile(planId int64, workDir string, name string) (string, erro...
  function ParseConfig (line 195) | func ParseConfig(data TaskData) (*types.PlanConfig, error) {

FILE: pkg/controller/plan/worker.go
  type Handler (line 31) | type Handler interface
  type handlerTask (line 39) | type handlerTask struct
    method GetPlanId (line 43) | func (t handlerTask) GetPlanId() int64     { return t.data.PlanId }
    method Step (line 44) | func (t handlerTask) Step() model.PlanStep { return model.RunningPlanS...
  function newHandlerTask (line 46) | func newHandlerTask(data TaskData) handlerTask {
  method Run (line 50) | func (p *plan) Run(ctx context.Context, workers int) error {
  method worker (line 65) | func (p *plan) worker(ctx context.Context) {
  method process (line 70) | func (p *plan) process(ctx context.Context) bool {
  type TaskData (line 81) | type TaskData struct
    method validate (line 87) | func (t TaskData) validate() error {
  method getTaskData (line 91) | func (p *plan) getTaskData(ctx context.Context, planId int64) (TaskData,...
  method syncHandler (line 114) | func (p *plan) syncHandler(ctx context.Context, planId int64) {
  method createPlanTasksIfNotExist (line 146) | func (p *plan) createPlanTasksIfNotExist(tasks ...Handler) error {
  method WorkDir (line 179) | func (p *plan) WorkDir() string {
  method GetRunner (line 183) | func (p *plan) GetRunner(osImage string) (string, error) {
  method syncStatus (line 198) | func (p *plan) syncStatus(ctx context.Context, planId int64) error {
  method syncTasks (line 218) | func (p *plan) syncTasks(tasks ...Handler) error {

FILE: pkg/controller/tenant/tenant.go
  type TenantGetter (line 31) | type TenantGetter interface
  type Interface (line 35) | type Interface interface
  type tenant (line 43) | type tenant struct
    method Create (line 48) | func (t *tenant) Create(ctx context.Context, req *types.CreateTenantRe...
    method Update (line 73) | func (t *tenant) Update(ctx context.Context, tid int64, req *types.Upd...
    method Delete (line 99) | func (t *tenant) Delete(ctx context.Context, tid int64) error {
    method Get (line 109) | func (t *tenant) Get(ctx context.Context, tid int64) (*types.Tenant, e...
    method List (line 121) | func (t *tenant) List(ctx context.Context) ([]types.Tenant, error) {
    method model2Type (line 135) | func (t *tenant) model2Type(o *model.Tenant) *types.Tenant {
  function NewTenant (line 150) | func NewTenant(cfg config.Config, f db.ShareDaoFactory) *tenant {

FILE: pkg/controller/user/user.go
  function init (line 42) | func init() {
  type UserGetter (line 47) | type UserGetter interface
  type Interface (line 51) | type Interface interface
  type user (line 70) | type user struct
    method Create (line 76) | func (u *user) Create(ctx context.Context, req *types.CreateUserReques...
    method Update (line 129) | func (u *user) Update(ctx context.Context, uid int64, req *types.Updat...
    method preResetPassword (line 145) | func (u *user) preResetPassword(ctx context.Context, userId int64, ope...
    method preChangePassword (line 158) | func (u *user) preChangePassword(ctx context.Context, userId int64, op...
    method UpdatePassword (line 178) | func (u *user) UpdatePassword(ctx context.Context, userId int64, req *...
    method Delete (line 217) | func (u *user) Delete(ctx context.Context, userId int64) error {
    method Get (line 228) | func (u *user) Get(ctx context.Context, userId int64) (*types.User, er...
    method List (line 241) | func (u *user) List(ctx context.Context, req *types.ListUserRequest) (...
    method GetCount (line 286) | func (u *user) GetCount(ctx context.Context, opts types.ListOptions) (...
    method GetStatus (line 297) | func (u *user) GetStatus(ctx context.Context, uid int64) (int, error) {
    method Login (line 316) | func (u *user) Login(ctx context.Context, req *types.LoginRequest) (*t...
    method Logout (line 354) | func (u *user) Logout(ctx context.Context, userId int64) error {
    method GetLoginToken (line 359) | func (u *user) GetLoginToken(ctx context.Context, userId int64) (strin...
    method GetTokenKey (line 368) | func (u *user) GetTokenKey() []byte {
  function model2Type (line 374) | func model2Type(o *model.User) *types.User {
  function NewUser (line 393) | func NewUser(cfg config.Config, f db.ShareDaoFactory, e *casbin.SyncedEn...

FILE: pkg/controller/util/util.go
  function MakeDbOptions (line 31) | func MakeDbOptions(ctx context.Context) (opts []db.Options) {
  function SetIdRangeContext (line 39) | func SetIdRangeContext(c *gin.Context, enforcer *casbin.SyncedEnforcer, ...
  type BindingQueryCondition (line 65) | type BindingQueryCondition
  function QueryWithGroupName (line 67) | func QueryWithGroupName(name string) BindingQueryCondition {
  function QueryWithUserName (line 74) | func QueryWithUserName(name string) BindingQueryCondition {
  function GetGroupBindings (line 81) | func GetGroupBindings(enforcer *casbin.SyncedEnforcer, conds ...BindingQ...
  type policyConditions (line 102) | type policyConditions struct
    method get (line 112) | func (c *policyConditions) get() (conds []string) {
  function newPolicyConditions (line 106) | func newPolicyConditions(name string) *policyConditions {
  type PolicyCondition (line 123) | type PolicyCondition
  function WithObjectType (line 125) | func WithObjectType(t model.ObjectType) PolicyCondition {
  function WithStringID (line 132) | func WithStringID(sid string) PolicyCondition {
  function WithOperation (line 138) | func WithOperation(op model.Operation) PolicyCondition {
  function GetUserPolicies (line 145) | func GetUserPolicies(enforcer *casbin.SyncedEnforcer, user *model.User, ...
  function GetGroupPolicy (line 162) | func GetGroupPolicy(enforcer *casbin.SyncedEnforcer, name string) (*mode...

FILE: pkg/db/audit.go
  type AuditInterface (line 29) | type AuditInterface interface
  type audit (line 38) | type audit struct
    method Create (line 46) | func (a *audit) Create(ctx context.Context, object *model.Audit) (*mod...
    method Get (line 57) | func (a *audit) Get(ctx context.Context, aid int64) (*model.Audit, err...
    method List (line 68) | func (a *audit) List(ctx context.Context, opts ...Options) ([]model.Au...
    method BatchDelete (line 81) | func (a *audit) BatchDelete(ctx context.Context, opts ...Options) (int...
    method Count (line 91) | func (a *audit) Count(ctx context.Context, opts ...Options) (int64, er...
  function newAudit (line 42) | func newAudit(db *gorm.DB) AuditInterface {

FILE: pkg/db/cluster.go
  type ClusterInterface (line 29) | type ClusterInterface interface
  type cluster (line 44) | type cluster struct
    method Create (line 48) | func (c *cluster) Create(ctx context.Context, object *model.Cluster, f...
    method Update (line 70) | func (c *cluster) Update(ctx context.Context, cid int64, resourceVersi...
    method InternalUpdate (line 87) | func (c *cluster) InternalUpdate(ctx context.Context, cid int64, updat...
    method Delete (line 101) | func (c *cluster) Delete(ctx context.Context, cluster *model.Cluster, ...
    method Get (line 120) | func (c *cluster) Get(ctx context.Context, cid int64, opts ...Options)...
    method List (line 136) | func (c *cluster) List(ctx context.Context, opts ...Options) ([]model....
    method Count (line 149) | func (c *cluster) Count(ctx context.Context, opts ...Options) (int64, ...
    method GetClusterByName (line 161) | func (c *cluster) GetClusterByName(ctx context.Context, name string) (...
    method UpdateByPlan (line 173) | func (c *cluster) UpdateByPlan(ctx context.Context, planId int64, upda...
  function newCluster (line 187) | func newCluster(db *gorm.DB) ClusterInterface {

FILE: pkg/db/factory.go
  type ShareDaoFactory (line 23) | type ShareDaoFactory interface
  type shareDaoFactory (line 32) | type shareDaoFactory struct
    method Cluster (line 36) | func (f *shareDaoFactory) Cluster() ClusterInterface       { return ne...
    method Tenant (line 37) | func (f *shareDaoFactory) Tenant() TenantInterface         { return ne...
    method User (line 38) | func (f *shareDaoFactory) User() UserInterface             { return ne...
    method Plan (line 39) | func (f *shareDaoFactory) Plan() PlanInterface             { return ne...
    method Audit (line 40) | func (f *shareDaoFactory) Audit() AuditInterface           { return ne...
    method Repository (line 41) | func (f *shareDaoFactory) Repository() RepositoryInterface { return ne...
  function NewDaoFactory (line 43) | func NewDaoFactory(db *gorm.DB, migrate bool) (ShareDaoFactory, error) {

FILE: pkg/db/logger.go
  type SQLs (line 27) | type SQLs
  type DBLogger (line 29) | type DBLogger struct
    method LogMode (line 44) | func (l *DBLogger) LogMode(level logger.LogLevel) logger.Interface {
    method Info (line 49) | func (l *DBLogger) Info(ctx context.Context, msg string, data ...inter...
    method Warn (line 51) | func (l *DBLogger) Warn(ctx context.Context, msg string, data ...inter...
    method Error (line 53) | func (l *DBLogger) Error(ctx context.Context, msg string, data ...inte...
    method Trace (line 55) | func (l *DBLogger) Trace(ctx context.Context, begin time.Time, fc func...
  constant SQLContextKey (line 35) | SQLContextKey = "sqls"
  function NewLogger (line 37) | func NewLogger(level logger.LogLevel, slowThreshold time.Duration) *DBLo...
  function WithDBContext (line 67) | func WithDBContext(ctx context.Context) context.Context {
  function GetSQLs (line 72) | func GetSQLs(ctx context.Context) SQLs {

FILE: pkg/db/migrator.go
  type migrator (line 25) | type migrator struct
    method AutoMigrate (line 30) | func (m *migrator) AutoMigrate() error {
    method CreateTables (line 34) | func (m *migrator) CreateTables(dst ...interface{}) error {
  function newMigrator (line 48) | func newMigrator(db *gorm.DB) *migrator {

FILE: pkg/db/model/audit.go
  function init (line 25) | func init() {
  type AuditOperationStatus (line 29) | type AuditOperationStatus
    method String (line 37) | func (s AuditOperationStatus) String() string {
  constant AuditOpFail (line 32) | AuditOpFail    AuditOperationStatus = iota
  constant AuditOpSuccess (line 33) | AuditOpSuccess
  constant AuditOpUnknown (line 34) | AuditOpUnknown
  type Audit (line 48) | type Audit struct
    method String (line 65) | func (a *Audit) String() string {
    method TableName (line 70) | func (a *Audit) TableName() string {

FILE: pkg/db/model/cluster.go
  function init (line 21) | func init() {
  type ClusterType (line 26) | type ClusterType
  constant ClusterTypeStandard (line 29) | ClusterTypeStandard ClusterType = iota
  constant ClusterTypeCustom (line 30) | ClusterTypeCustom
  type ClusterStatus (line 33) | type ClusterStatus
  constant ClusterStatusRunning (line 36) | ClusterStatusRunning ClusterStatus = iota
  constant ClusterStatusDeploy (line 37) | ClusterStatusDeploy
  constant ClusterStatusUnStart (line 38) | ClusterStatusUnStart
  constant ClusterStatusFailed (line 39) | ClusterStatusFailed
  constant ClusterStatusError (line 40) | ClusterStatusError
  type Cluster (line 44) | type Cluster struct
    method TableName (line 77) | func (*Cluster) TableName() string {

FILE: pkg/db/model/model.go
  function register (line 21) | func register(model ...interface{}) {
  function GetMigrationModels (line 26) | func GetMigrationModels() []interface{} {

FILE: pkg/db/model/pixiu/model.go
  type Model (line 24) | type Model struct
    method GetSID (line 31) | func (m Model) GetSID() string {

FILE: pkg/db/model/plan.go
  function init (line 23) | func init() {
  type Plan (line 27) | type Plan struct
    method TableName (line 34) | func (plan *Plan) TableName() string {
  type KubeRole (line 38) | type KubeRole
  constant MasterRole (line 41) | MasterRole string = "master"
  constant NodeRole (line 42) | NodeRole   string = "node"
  type CRI (line 45) | type CRI
  constant DockerCRI (line 48) | DockerCRI     CRI = "docker"
  constant ContainerdCRI (line 49) | ContainerdCRI CRI = "containerd"
  type Node (line 52) | type Node struct
    method TableName (line 63) | func (node *Node) TableName() string {
  type Config (line 67) | type Config struct
    method TableName (line 79) | func (config *Config) TableName() string {
  type PlanStep (line 83) | type PlanStep
  constant UnStartedPlanStep (line 86) | UnStartedPlanStep PlanStep = iota
  constant RunningPlanStep (line 87) | RunningPlanStep
  constant FailedPlanStep (line 88) | FailedPlanStep
  constant CompletedPlanStep (line 89) | CompletedPlanStep
  type TaskStatus (line 92) | type TaskStatus
  constant FailedPlanStatus (line 95) | FailedPlanStatus  TaskStatus = "已失败"
  constant SuccessPlanStatus (line 96) | SuccessPlanStatus TaskStatus = "已成功"
  constant UnStartPlanStatus (line 97) | UnStartPlanStatus TaskStatus = "未开始"
  constant RunningPlanStatus (line 98) | RunningPlanStatus TaskStatus = "运行中"
  type Task (line 101) | type Task struct
    method TableName (line 111) | func (task *Task) TableName() string {

FILE: pkg/db/model/rbac.go
  constant AdminGroup (line 28) | AdminGroup = "root"
  constant SidAll (line 29) | SidAll     = "*"
  type Operation (line 32) | type Operation
    method String (line 42) | func (o Operation) String() string {
  constant OpRead (line 35) | OpRead   Operation = "read"
  constant OpCreate (line 36) | OpCreate Operation = "create"
  constant OpUpdate (line 37) | OpUpdate Operation = "update"
  constant OpDelete (line 38) | OpDelete Operation = "delete"
  constant OpAll (line 39) | OpAll    Operation = "*"
  type ObjectType (line 54) | type ObjectType
    method String (line 65) | func (o ObjectType) String() string {
  constant ObjectUser (line 57) | ObjectUser    ObjectType = "users"
  constant ObjectCluster (line 58) | ObjectCluster ObjectType = "clusters"
  constant ObjectTenant (line 59) | ObjectTenant  ObjectType = "tenants"
  constant ObjectPlan (line 60) | ObjectPlan    ObjectType = "plans"
  constant ObjectAuth (line 61) | ObjectAuth    ObjectType = "auth"
  constant ObjectAll (line 62) | ObjectAll     ObjectType = "*"
  type RBACInterface (line 79) | type RBACInterface interface
  constant RBACModel (line 83) | RBACModel = `
  type CasbinRBACImpl (line 100) | type CasbinRBACImpl struct
  type Policy (line 102) | type Policy interface
  type UserPolicy (line 108) | type UserPolicy
    method Raw (line 116) | func (p UserPolicy) Raw() []string {
    method GetUserName (line 120) | func (p UserPolicy) GetUserName() string {
    method GetObjectType (line 124) | func (p UserPolicy) GetObjectType() ObjectType {
    method GetSID (line 128) | func (p UserPolicy) GetSID() string {
    method GetOperation (line 132) | func (p UserPolicy) GetOperation() Operation {
  function NewUserPolicy (line 112) | func NewUserPolicy(userName string, obj ObjectType, sid string, op Opera...
  type GroupPolicy (line 138) | type GroupPolicy
    method Raw (line 146) | func (p GroupPolicy) Raw() []string {
    method GetGroupName (line 150) | func (p GroupPolicy) GetGroupName() string {
    method GetObjectType (line 154) | func (p GroupPolicy) GetObjectType() ObjectType {
    method GetSID (line 158) | func (p GroupPolicy) GetSID() string {
    method GetOperation (line 162) | func (p GroupPolicy) GetOperation() Operation {
  function NewGroupPolicy (line 142) | func NewGroupPolicy(groupName string, obj ObjectType, sid string, op Ope...
  type GroupBinding (line 168) | type GroupBinding
    method Raw (line 175) | func (p GroupBinding) Raw() []string {
    method GetUserName (line 179) | func (p GroupBinding) GetUserName() string {
    method GetGroupName (line 183) | func (p GroupBinding) GetGroupName() string {
  function NewGroupBinding (line 171) | func NewGroupBinding(userName, groupName string) GroupBinding {
  function IsAdminPolicy (line 191) | func IsAdminPolicy(policy Policy) bool {
  function BindingToAdmin (line 201) | func BindingToAdmin(policies []GroupBinding) bool {
  function NewPolicyFromModels (line 212) | func NewPolicyFromModels(user *User, obj ObjectType, model pixiu.Model, ...
  function GetIdRangeFromPolicy (line 219) | func GetIdRangeFromPolicy(policies []Policy) (all bool, ids []int64) {

FILE: pkg/db/model/rbac_test.go
  function TestGetIdRangeFromPolicies (line 25) | func TestGetIdRangeFromPolicies(t *testing.T) {
  function TestIsAdminPolicy (line 169) | func TestIsAdminPolicy(t *testing.T) {
  function TestBindingToAdmin (line 237) | func TestBindingToAdmin(t *testing.T) {

FILE: pkg/db/model/repository.go
  function init (line 25) | func init() {
  type Repository (line 29) | type Repository struct
    method TableName (line 37) | func (*Repository) TableName() string {
  type ChartIndex (line 41) | type ChartIndex struct
  type Entries (line 46) | type Entries
  type ChartVersion (line 48) | type ChartVersion struct
  type Dependency (line 65) | type Dependency struct
  type Maintainer (line 73) | type Maintainer struct

FILE: pkg/db/model/tenant.go
  function init (line 21) | func init() {
  type Tenant (line 25) | type Tenant struct
    method TableName (line 33) | func (tenant *Tenant) TableName() string {

FILE: pkg/db/model/user.go
  function init (line 21) | func init() {
  type UserRole (line 25) | type UserRole
  constant RoleUser (line 28) | RoleUser  UserRole = iota
  constant RoleAdmin (line 29) | RoleAdmin
  constant RoleRoot (line 30) | RoleRoot
  type UserStatus (line 33) | type UserStatus
  type User (line 35) | type User struct
    method TableName (line 48) | func (user *User) TableName() string {

FILE: pkg/db/options.go
  type Options (line 25) | type Options
  function WithOrderByASC (line 27) | func WithOrderByASC() Options {
  function WithOrderByDesc (line 33) | func WithOrderByDesc() Options {
  function WithOffset (line 39) | func WithOffset(offset int) Options {
  function WithCreatedBefore (line 45) | func WithCreatedBefore(t time.Time) Options {
  function WithLimit (line 51) | func WithLimit(limit int) Options {
  function WithIDIn (line 61) | func WithIDIn(ids ...int64) Options {
  function WithAliasNameLike (line 68) | func WithAliasNameLike(name string) Options {
  function WithClusterStatus (line 77) | func WithClusterStatus(status int) Options {
  function WithUserNameLike (line 83) | func WithUserNameLike(name string) Options {
  function WithUserPhoneLike (line 92) | func WithUserPhoneLike(phone string) Options {
  function WithUserEmailLike (line 101) | func WithUserEmailLike(email string) Options {
  function WithUserStatus (line 110) | func WithUserStatus(status int) Options {
  function WithAuditOperatorLike (line 116) | func WithAuditOperatorLike(operator string) Options {
  function WithAuditAction (line 125) | func WithAuditAction(action string) Options {
  function WithAuditObjectType (line 134) | func WithAuditObjectType(ot string) Options {
  function WithAuditStatus (line 143) | func WithAuditStatus(status uint8) Options {
  function WithAuditCreatedAfter (line 149) | func WithAuditCreatedAfter(t time.Time) Options {
  function WithAuditCluster (line 158) | func WithAuditCluster(cluster string) Options {
  function WithPlanNameLike (line 164) | func WithPlanNameLike(name string) Options {

FILE: pkg/db/plan.go
  type PlanInterface (line 29) | type PlanInterface interface
  type plan (line 69) | type plan struct
    method Create (line 75) | func (p *plan) Create(ctx context.Context, object *model.Plan, opts .....
    method Update (line 106) | func (p *plan) Update(ctx context.Context, pid int64, resourceVersion ...
    method Delete (line 123) | func (p *plan) Delete(ctx context.Context, pid int64) (*model.Plan, er...
    method Get (line 135) | func (p *plan) Get(ctx context.Context, pid int64) (*model.Plan, error) {
    method List (line 144) | func (p *plan) List(ctx context.Context, opts ...Options) ([]model.Pla...
    method Count (line 157) | func (p *plan) Count(ctx context.Context, opts ...Options) (int64, err...
    method CreateNode (line 169) | func (p *plan) CreateNode(ctx context.Context, object *model.Node) (*m...
    method TxCreateNode (line 181) | func (p *plan) TxCreateNode(ctx context.Context, tx *gorm.DB, object *...
    method UpdateNode (line 189) | func (p *plan) UpdateNode(ctx context.Context, nodeId int64, resourceV...
    method DeleteNode (line 205) | func (p *plan) DeleteNode(ctx context.Context, nodeId int64) (*model.N...
    method DeleteNodesByPlan (line 217) | func (p *plan) DeleteNodesByPlan(ctx context.Context, planId int64) er...
    method DeleteNodesByNames (line 225) | func (p *plan) DeleteNodesByNames(ctx context.Context, planId int64, n...
    method GetNodeByName (line 233) | func (p *plan) GetNodeByName(ctx context.Context, planId int64, name s...
    method GetNode (line 242) | func (p *plan) GetNode(ctx context.Context, nodeId int64) (*model.Node...
    method ListNodes (line 251) | func (p *plan) ListNodes(ctx context.Context, pid int64, opts ...Optio...
    method CreateConfig (line 264) | func (p *plan) CreateConfig(ctx context.Context, object *model.Config)...
    method TxCreateConfig (line 276) | func (p *plan) TxCreateConfig(ctx context.Context, tx *gorm.DB, object...
    method UpdateConfig (line 284) | func (p *plan) UpdateConfig(ctx context.Context, cid int64, resourceVe...
    method DeleteConfig (line 300) | func (p *plan) DeleteConfig(ctx context.Context, cid int64) (*model.Co...
    method DeleteConfigByPlan (line 312) | func (p *plan) DeleteConfigByPlan(ctx context.Context, planId int64) e...
    method GetConfig (line 319) | func (p *plan) GetConfig(ctx context.Context, cid int64) (*model.Confi...
    method ListConfigs (line 328) | func (p *plan) ListConfigs(ctx context.Context, opts ...Options) ([]mo...
    method GetConfigByPlan (line 341) | func (p *plan) GetConfigByPlan(ctx context.Context, planId int64) (*mo...
    method CreateTask (line 350) | func (p *plan) CreateTask(ctx context.Context, object *model.Task) (*m...
    method UpdateTask (line 361) | func (p *plan) UpdateTask(ctx context.Context, pid int64, name string,...
    method DeleteTask (line 373) | func (p *plan) DeleteTask(ctx context.Context, pid int64) error {
    method ListTasks (line 381) | func (p *plan) ListTasks(ctx context.Context, pid int64, opts ...Optio...
    method GetNewestTask (line 394) | func (p *plan) GetNewestTask(ctx context.Context, pid int64) (*model.T...
    method GetTaskById (line 406) | func (p *plan) GetTaskById(ctx context.Context, taskId int64) (*model....
    method GetTaskByName (line 415) | func (p *plan) GetTaskByName(ctx context.Context, planId int64, name s...
  type CreatePlanOption (line 73) | type CreatePlanOption
  function newPlan (line 424) | func newPlan(db *gorm.DB) *plan {

FILE: pkg/db/repository.go
  type RepositoryInterface (line 28) | type RepositoryInterface interface
  type repository (line 37) | type repository struct
    method Create (line 47) | func (r *repository) Create(ctx context.Context, object *model.Reposit...
    method Update (line 58) | func (r *repository) Update(ctx context.Context, id int64, resourceVer...
    method Delete (line 75) | func (r *repository) Delete(ctx context.Context, id int64) error {
    method Get (line 88) | func (r *repository) Get(ctx context.Context, id int64) (*model.Reposi...
    method GetByName (line 97) | func (r *repository) GetByName(ctx context.Context, name string) (*mod...
    method List (line 106) | func (r *repository) List(ctx context.Context) ([]*model.Repository, e...
  function newRepository (line 41) | func newRepository(db *gorm.DB) RepositoryInterface {

FILE: pkg/db/tenant.go
  type TenantInterface (line 29) | type TenantInterface interface
  type tenant (line 39) | type tenant struct
    method Create (line 43) | func (t *tenant) Create(ctx context.Context, object *model.Tenant) (*m...
    method Update (line 54) | func (t *tenant) Update(ctx context.Context, tid int64, resourceVersio...
    method Delete (line 71) | func (t *tenant) Delete(ctx context.Context, tid int64) (*model.Tenant...
    method Get (line 86) | func (t *tenant) Get(ctx context.Context, tid int64) (*model.Tenant, e...
    method List (line 98) | func (t *tenant) List(ctx context.Context, opts ...Options) ([]model.T...
    method GetTenantByName (line 111) | func (t *tenant) GetTenantByName(ctx context.Context, name string) (*m...
  function newTenant (line 123) | func newTenant(db *gorm.DB) *tenant {

FILE: pkg/db/user.go
  type UserInterface (line 29) | type UserInterface interface
  type user (line 42) | type user struct
    method Create (line 46) | func (u *user) Create(ctx context.Context, object *model.User, fns ......
    method Update (line 69) | func (u *user) Update(ctx context.Context, uid int64, resourceVersion ...
    method Delete (line 84) | func (u *user) Delete(ctx context.Context, uid int64) error {
    method Get (line 88) | func (u *user) Get(ctx context.Context, uid int64) (*model.User, error) {
    method GetRoot (line 100) | func (u *user) GetRoot(ctx context.Context) (*model.User, error) {
    method List (line 114) | func (u *user) List(ctx context.Context, opts ...Options) ([]model.Use...
    method Count (line 127) | func (u *user) Count(ctx context.Context, opts ...Options) (int64, err...
    method GetUserByName (line 140) | func (u *user) GetUserByName(ctx context.Context, userName string) (*m...
  function newUser (line 152) | func newUser(db *gorm.DB) *user {

FILE: pkg/jobmanager/audit_cleaner.go
  constant DefaultSchedule (line 27) | DefaultSchedule     = "0 0 * * 6"
  constant DefaultDaysReserved (line 28) | DefaultDaysReserved = 30
  type AuditsCleaner (line 31) | type AuditsCleaner struct
    method Name (line 55) | func (ac *AuditsCleaner) Name() string {
    method CronSpec (line 59) | func (ac *AuditsCleaner) CronSpec() string {
    method LogLevel (line 63) | func (ac *AuditsCleaner) LogLevel() logutil.LogLevel {
    method Do (line 67) | func (ac *AuditsCleaner) Do(ctx *JobContext) (err error) {
  type AuditOptions (line 36) | type AuditOptions struct
    method Valid (line 80) | func (a *AuditOptions) Valid() error {
  function DefaultOptions (line 41) | func DefaultOptions() AuditOptions {
  function NewAuditsCleaner (line 48) | func NewAuditsCleaner(cfg AuditOptions, dao db.ShareDaoFactory) *AuditsC...

FILE: pkg/jobmanager/cluster_syncer.go
  constant DefaultSyncInterval (line 35) | DefaultSyncInterval = "@every 5s"
  type ClusterSyncer (line 38) | type ClusterSyncer struct
    method Name (line 48) | func (cs *ClusterSyncer) Name() string {
    method CronSpec (line 52) | func (cs *ClusterSyncer) CronSpec() string {
    method LogLevel (line 56) | func (cs *ClusterSyncer) LogLevel() logutil.LogLevel {
    method Do (line 60) | func (cs *ClusterSyncer) Do(ctx *JobContext) (err error) {
  function NewClusterSyncer (line 42) | func NewClusterSyncer(f db.ShareDaoFactory) *ClusterSyncer {
  function doSync (line 92) | func doSync(f db.ShareDaoFactory, cluster model.Cluster) error {
  function parseStatus (line 126) | func parseStatus(update map[string]interface{}, status model.ClusterStat...
  function getNewestKubeStatus (line 138) | func getNewestKubeStatus(cluster model.Cluster) (string, string, error) {
  function parseKubeNodeStatus (line 175) | func parseKubeNodeStatus(node *v1.Node) string {

FILE: pkg/jobmanager/context.go
  type JobContext (line 26) | type JobContext struct
    method Log (line 40) | func (c *JobContext) Log(level logutil.LogLevel, err error) {
  function NewJobContext (line 31) | func NewJobContext(name string, cfg *logutil.LogOptions) *JobContext {

FILE: pkg/jobmanager/manager.go
  type Job (line 25) | type Job interface
  type Manager (line 40) | type Manager struct
    method Run (line 57) | func (m *Manager) Run() {
    method Stop (line 61) | func (m *Manager) Stop() {
  function NewManager (line 44) | func NewManager(lc *logutil.LogOptions, jobs ...Job) *Manager {

FILE: pkg/static/localfile.go
  type localFileSystem (line 27) | type localFileSystem struct
    method Exists (line 40) | func (l *localFileSystem) Exists(prefix string, file string) bool {
  function LocalFile (line 33) | func LocalFile(root string, indexes bool) *localFileSystem {

FILE: pkg/static/static.go
  type ServeFileSystem (line 26) | type ServeFileSystem interface
  function ServeRoot (line 31) | func ServeRoot(urlPrefix, root string) gin.HandlerFunc {
  function Serve (line 36) | func Serve(urlPrefix string, fs ServeFileSystem) gin.HandlerFunc {
  function ServeCached (line 42) | func ServeCached(urlPrefix string, fs ServeFileSystem, cacheAge uint) gi...

FILE: pkg/types/helm.go
  type Release (line 19) | type Release struct
  type RepoId (line 27) | type RepoId struct
  type RepoName (line 31) | type RepoName struct
  type RepoURL (line 36) | type RepoURL struct
  type ChartValues (line 39) | type ChartValues struct
  type ReleaseHistory (line 44) | type ReleaseHistory struct
  type CreateRepository (line 48) | type CreateRepository struct
  type UpdateRepository (line 55) | type UpdateRepository struct

FILE: pkg/types/meta.go
  constant timeLayout (line 40) | timeLayout = "2006-01-02 15:04:05.999999999"
  constant MsgData (line 42) | MsgData   = '1'
  constant MsgResize (line 43) | MsgResize = '2'
  method SetId (line 46) | func (c *Cluster) SetId(i int64) {
  method SetReplicaSets (line 50) | func (o *KubeObject) SetReplicaSets(replicaSets []appv1.ReplicaSet) {
  method GetReplicaSets (line 57) | func (o *KubeObject) GetReplicaSets() []appv1.ReplicaSet {
  method SetPods (line 64) | func (o *KubeObject) SetPods(pods []v1.Pod) {
  method GetPods (line 71) | func (o *KubeObject) GetPods() []v1.Pod {
  function FormatTime (line 78) | func FormatTime(GmtCreate time.Time, GmtModified time.Time) TimeSpec {
  function NewTerminalSession (line 86) | func NewTerminalSession(w http.ResponseWriter, r *http.Request) (*Termin...
  method Read (line 110) | func (t *TerminalSession) Read(p []byte) (int, error) {
  method Write (line 138) | func (t *TerminalSession) Write(p []byte) (int, error) {
  method Done (line 153) | func (t *TerminalSession) Done() {
  method Close (line 158) | func (t *TerminalSession) Close() error {
  method Next (line 163) | func (t *TerminalSession) Next() *remotecommand.TerminalSize {
  function NewTurn (line 172) | func NewTurn(wsConn *websocket.Conn, sshClient *ssh.Client) (*Turn, erro...
  method Write (line 202) | func (t *Turn) Write(p []byte) (n int, err error) {
  method Close (line 212) | func (t *Turn) Close() error {
  method Read (line 219) | func (t *Turn) Read(p []byte) (n int, err error) {
  method StartLoopRead (line 232) | func (t *Turn) StartLoopRead(ctx context.Context, wg *sync.WaitGroup, lo...
  method loopRead (line 240) | func (t *Turn) loopRead(logBuff *bytes.Buffer, context context.Context) ...
  method dataDo (line 266) | func (t *Turn) dataDo(body []byte, logBuff *bytes.Buffer) error {
  type Resize (line 277) | type Resize struct
  method resizeDo (line 282) | func (t *Turn) resizeDo(body []byte) error {
  method sessionWait (line 297) | func (t *Turn) sessionWait() error {
  method StartSessionWait (line 304) | func (t *Turn) StartSessionWait(wg *sync.WaitGroup) {
  function decode (line 312) | func decode(p []byte) []byte {
  method Marshal (line 317) | func (a *PlanNodeAuth) Marshal() (string, error) {
  method Unmarshal (line 325) | func (a *PlanNodeAuth) Unmarshal(s string) error {
  method Marshal (line 332) | func (ks *KubernetesSpec) Marshal() (string, error) {
  method Unmarshal (line 340) | func (ks *KubernetesSpec) Unmarshal(s string) error {
  method Marshal (line 347) | func (ns *NetworkSpec) Marshal() (string, error) {
  method Unmarshal (line 355) | func (ns *NetworkSpec) Unmarshal(s string) error {
  method Marshal (line 362) | func (rs *RuntimeSpec) Marshal() (string, error) {
  method Unmarshal (line 370) | func (rs *RuntimeSpec) Unmarshal(s string) error {
  method Marshal (line 377) | func (cs ComponentSpec) Marshal() (string, error) {
  method Unmarshal (line 385) | func (cs *ComponentSpec) Unmarshal(s string) error {
  method IsDocker (line 392) | func (rs *RuntimeSpec) IsDocker() bool {
  method IsContainerd (line 396) | func (rs *RuntimeSpec) IsContainerd() bool {
  method IsPaged (line 400) | func (p PageRequest) IsPaged() bool {
  method Offset (line 404) | func (p PageRequest) Offset(total int) (int, int, error) {
  method Marshal (line 418) | func (node *KubeNode) Marshal() (string, error) {
  method Unmarshal (line 426) | func (node *KubeNode) Unmarshal(s string) error {

FILE: pkg/types/request.go
  constant AllNamespace (line 21) | AllNamespace = "all_namespaces"
  type LoginRequest (line 25) | type LoginRequest struct
  type CreateUserRequest (line 30) | type CreateUserRequest struct
  type UpdateUserRequest (line 42) | type UpdateUserRequest struct
  type UpdateUserPasswordRequest (line 51) | type UpdateUserPasswordRequest struct
  type CreateClusterRequest (line 58) | type CreateClusterRequest struct
  type UpdateClusterRequest (line 67) | type UpdateClusterRequest struct
  type ProtectClusterRequest (line 74) | type ProtectClusterRequest struct
  type CreateTenantRequest (line 79) | type CreateTenantRequest struct
  type UpdateTenantRequest (line 84) | type UpdateTenantRequest struct
  type CreatePlanRequest (line 90) | type CreatePlanRequest struct
  type UpdatePlanRequest (line 98) | type UpdatePlanRequest struct
  type CreatePlanNodeRequest (line 107) | type CreatePlanNodeRequest struct
  type UpdatePlanNodeRequest (line 116) | type UpdatePlanNodeRequest struct
  type CreatePlanConfigRequest (line 126) | type CreatePlanConfigRequest struct
  type UpdatePlanConfigRequest (line 138) | type UpdatePlanConfigRequest struct
  type RBACPolicyRequest (line 142) | type RBACPolicyRequest struct
  type ListRBACPolicyRequest (line 151) | type ListRBACPolicyRequest struct
  type GroupBindingRequest (line 158) | type GroupBindingRequest struct
  type ListGroupBindingRequest (line 163) | type ListGroupBindingRequest struct
  type PageRequest (line 169) | type PageRequest struct
  type QueryOption (line 174) | type QueryOption struct
  type ListClusterRequest (line 180) | type ListClusterRequest struct
  type ListPlanRequest (line 187) | type ListPlanRequest struct
  type ListUserRequest (line 194) | type ListUserRequest struct
  type WebSSHRequest (line 203) | type WebSSHRequest struct
  type LoginResponse (line 212) | type LoginResponse struct
  type PageResponse (line 221) | type PageResponse struct

FILE: pkg/types/types.go
  type PixiuObjectMeta (line 33) | type PixiuObjectMeta struct
  type PixiuMeta (line 39) | type PixiuMeta struct
  type TimeMeta (line 46) | type TimeMeta struct
  type KubeNode (line 53) | type KubeNode struct
  type Cluster (line 58) | type Cluster struct
  type KubernetesMeta (line 88) | type KubernetesMeta struct
  type Resources (line 99) | type Resources struct
  type User (line 104) | type User struct
  type Tenant (line 118) | type Tenant struct
  type Plan (line 126) | type Plan struct
  type PlanNode (line 140) | type PlanNode struct
  type Audit (line 152) | type Audit struct
  type AuthType (line 169) | type AuthType
  constant NoneAuth (line 172) | NoneAuth     AuthType = "none"
  constant KeyAuth (line 173) | KeyAuth      AuthType = "key"
  constant PasswordAuth (line 174) | PasswordAuth AuthType = "password"
  type PlanNodeAuth (line 177) | type PlanNodeAuth struct
  type PlanTask (line 183) | type PlanTask struct
  type KeySpec (line 193) | type KeySpec struct
  type PasswordSpec (line 198) | type PasswordSpec struct
  type PlanConfig (line 203) | type PlanConfig struct
  type TimeSpec (line 218) | type TimeSpec struct
  type KubeObject (line 223) | type KubeObject struct
  type WebShellOptions (line 231) | type WebShellOptions struct
  type TerminalMessage (line 241) | type TerminalMessage struct
  type TerminalSession (line 252) | type TerminalSession struct
  type Turn (line 258) | type Turn struct
  type ListOptions (line 265) | type ListOptions struct
  type EventOptions (line 273) | type EventOptions struct
  type PodLogOptions (line 282) | type PodLogOptions struct
  type KubernetesSpec (line 287) | type KubernetesSpec struct
  type NetworkSpec (line 296) | type NetworkSpec struct
  type RuntimeSpec (line 304) | type RuntimeSpec struct
  type ComponentSpec (line 308) | type ComponentSpec struct
  type Helm (line 315) | type Helm struct
  type Prometheus (line 320) | type Prometheus struct
  type Grafana (line 325) | type Grafana struct
  type Haproxy (line 333) | type Haproxy struct
  type RBACPolicy (line 338) | type RBACPolicy struct
  type AuditListOptions (line 347) | type AuditListOptions struct

FILE: pkg/util/container/container.go
  type Container (line 34) | type Container struct
    method StartAndWaitForContainer (line 57) | func (c *Container) StartAndWaitForContainer(ctx context.Context, imag...
    method Close (line 88) | func (c *Container) Close() error {
    method ClearContainer (line 93) | func (c *Container) ClearContainer(ctx context.Context) error {
    method ListContainers (line 112) | func (c *Container) ListContainers(ctx context.Context) ([]types.Conta...
    method GetContainer (line 121) | func (c *Container) GetContainer(ctx context.Context, containerName st...
    method WaitContainer (line 141) | func (c *Container) WaitContainer(ctx context.Context, containerId str...
    method WatchContainerLog (line 189) | func (c *Container) WatchContainerLog(ctx context.Context, containerId...
  function NewContainer (line 42) | func NewContainer(action string, planId int64, dir string) (*Container, ...

FILE: pkg/util/errors/errors.go
  function IsRecordNotFound (line 60) | func IsRecordNotFound(err error) bool {
  function IsNotUpdated (line 64) | func IsNotUpdated(err error) bool {
  function IsUniqueConstraintError (line 68) | func IsUniqueConstraintError(err error) bool {

FILE: pkg/util/log/log.go
  type LogFormat (line 33) | type LogFormat
  constant LogFormatJson (line 36) | LogFormatJson LogFormat = "json"
  constant LogFormatText (line 37) | LogFormatText LogFormat = "text"
  constant ErrorLevel (line 46) | ErrorLevel LogLevel = klog.ErrorLevel
  constant InfoLevel (line 47) | InfoLevel  LogLevel = klog.InfoLevel
  constant DebugLevel (line 48) | DebugLevel LogLevel = klog.DebugLevel
  type LogOptions (line 51) | type LogOptions struct
    method Valid (line 66) | func (o *LogOptions) Valid() error {
    method Init (line 76) | func (o *LogOptions) Init() {
  function DefaultLogOptions (line 58) | func DefaultLogOptions() *LogOptions {
  constant SuccessMsg (line 94) | SuccessMsg = "SUCCESS"
  constant ErrorMsg (line 95) | ErrorMsg   = "ERROR"
  constant FailMsg (line 96) | FailMsg    = "FAIL"
  type Logger (line 99) | type Logger struct
    method WithLogField (line 113) | func (l *Logger) WithLogField(key string, value interface{}) {
    method WithLogFields (line 117) | func (l *Logger) WithLogFields(fields map[string]interface{}) {
    method Log (line 121) | func (l *Logger) Log(ctx context.Context, level LogLevel, err error) {
  function NewLogger (line 105) | func NewLogger(cfg *LogOptions) *Logger {

FILE: pkg/util/lru/lru.go
  type LRUCache (line 24) | type LRUCache struct
    method Contains (line 45) | func (c *LRUCache) Contains(key interface{}) bool {
    method Add (line 50) | func (c *LRUCache) Add(key, value interface{}) {
    method Get (line 72) | func (c *LRUCache) Get(key interface{}) (value interface{}) {
    method Len (line 83) | func (c *LRUCache) Len() int { return c.evictList.Len() }
  type entry (line 32) | type entry struct
  function NewLRUCache (line 37) | func NewLRUCache(cap int) *LRUCache {

FILE: pkg/util/ssh/ssh.go
  function NewSSHClient (line 28) | func NewSSHClient(sshConfig *types.WebSSHRequest) (*ssh.Client, error) {

FILE: pkg/util/token/token.go
  type Claims (line 26) | type Claims struct
  function GenerateToken (line 35) | func GenerateToken(uid int64, name string, jwtKey []byte) (string, error) {
  function ParseToken (line 53) | func ParseToken(tokenStr string, jwtKey []byte) (*Claims, error) {

FILE: pkg/util/util.go
  function init (line 30) | func init() {
  function EncryptUserPassword (line 37) | func EncryptUserPassword(origin string) (string, error) {
  function ValidateUserPassword (line 47) | func ValidateUserPassword(old, new string) error {
  function ValidateStrongPassword (line 52) | func ValidateStrongPassword(password string) bool {
  function GenerateRequestID (line 82) | func GenerateRequestID() string {
  function IsEmptyS (line 86) | func IsEmptyS(s string) bool {
  function IsDirectoryExists (line 90) | func IsDirectoryExists(path string) bool {
  function IsFileExists (line 102) | func IsFileExists(path string) bool {
  function EnsureDirectoryExists (line 114) | func EnsureDirectoryExists(path string) error {
  function WriteToFile (line 124) | func WriteToFile(filename string, data []byte) error {
  function BuildWebSocketConnection (line 128) | func BuildWebSocketConnection(w http.ResponseWriter, r *http.Request) (*...
  function DeduplicateIntSlice (line 140) | func DeduplicateIntSlice(s []int64) (ret []int64) {
  function More (line 155) | func More(a, b int) int {
  function Less (line 163) | func Less(a, b int) int {

FILE: pkg/util/util_test.go
  function TestValidateStrongPassword (line 24) | func TestValidateStrongPassword(t *testing.T) {
  function TestDeduplicateIntSlice (line 110) | func TestDeduplicateIntSlice(t *testing.T) {

FILE: pkg/util/uuid/uuid.go
  constant namePrefix (line 26) | namePrefix = "pixiu-"
  function NewUUID (line 29) | func NewUUID() string {
  function NewRandName (line 33) | func NewRandName(length int) string {

FILE: template/globals.go
  constant GlobalsTemplate (line 19) | GlobalsTemplate = `# Render below by Pixiu

FILE: template/hosts.go
  constant HostTemplate (line 19) | HostTemplate = `# Render below by Pixiu engine

FILE: template/multinode.go
  constant MultiModeTemplate (line 19) | MultiModeTemplate = `# Render below by Pixiu engine
Condensed preview — 158 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (832K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 718,
    "preview": "---\nname: Bug report\nlabels: [\"kind/bug\"]\nabout: Create a report to help us improve\n---\n\n**Describe the Bug**\nA clear an"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 1484,
    "preview": "---\nname: Feature Request\nabout: Have a good idea? Please don't hesitate to write it down, describe the new feature.\n---"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 1754,
    "preview": "#### What type of PR is this?\n\n<!--\nAdd one of the following kinds:\n/kind bug\n/kind cleanup\n/kind documentation\n/kind fe"
  },
  {
    "path": ".github/workflows/build-webshell-image.yml",
    "chars": 1362,
    "preview": "name: Publish webshell image\n\non:\n  push:\n    branches:\n      - \"master\"\n    paths:\n      - 'docker/Dockerfile-toolbox'\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 1135,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\nenv:\n  GO_VERSION: '1.1"
  },
  {
    "path": ".github/workflows/docker-image.yml",
    "chars": 1493,
    "preview": "name: Publish pixiu image\n\non:\n  push:\n    branches:\n      - \"master\"\n    paths-ignore:\n      - 'docs/**'\n\njobs:\n  build"
  },
  {
    "path": ".gitignore",
    "chars": 444,
    "preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin\ntestbin/*\n\n# Test binary, build with `go test -c"
  },
  {
    "path": "Makefile",
    "chars": 1076,
    "preview": ".PHONY: run build image push clean\n\ntag = v0.1\nreleaseName = pixiu\ndockerhubUser ?= jacky06\nk8sVersion ?= v1.23.6\nhelmVe"
  },
  {
    "path": "README.md",
    "chars": 2203,
    "preview": "# Pixiu Overview\n\nPixiu is an open source container platform for cloud-native application management.\n\n![Build Status][b"
  },
  {
    "path": "api/docs/docs.go",
    "chars": 31476,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/docs/swagger.json",
    "chars": 30257,
    "preview": "{\n    \"schemes\": [\n        \"http\",\n        \"https\"\n    ],\n    \"swagger\": \"2.0\",\n    \"info\": {\n        \"title\": \"Pixiu AP"
  },
  {
    "path": "api/docs/swagger.yaml",
    "chars": 14026,
    "preview": "definitions:\n  httputils.Response:\n    properties:\n      code:\n        description: 返回的状态码\n        type: integer\n      m"
  },
  {
    "path": "api/server/errors/errors.go",
    "chars": 2651,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/httpstatus/status.go",
    "chars": 602,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/httputils/docs.go",
    "chars": 869,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/httputils/httputils.go",
    "chars": 5841,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/httputils/httputils_test.go",
    "chars": 2367,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/admission.go",
    "chars": 708,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/audit.go",
    "chars": 5259,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/authentication.go",
    "chars": 2864,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/authorization.go",
    "chars": 3026,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/cors.go",
    "chars": 949,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/limiter.go",
    "chars": 1796,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/log.go",
    "chars": 1372,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/middleware/middleware.go",
    "chars": 1352,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/audit/audit.go",
    "chars": 1100,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/audit/audit_routes.go",
    "chars": 1554,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/auth/auth.go",
    "chars": 1432,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/auth/auth_routes.go",
    "chars": 2950,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/cluster/cluster.go",
    "chars": 2626,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/cluster/cluster_routes.go",
    "chars": 8913,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/cluster/helper.go",
    "chars": 846,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/cluster/informer.go",
    "chars": 1986,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/cluster/proxy.go",
    "chars": 1348,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/cluster/ws.go",
    "chars": 1471,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/helm/helm.go",
    "chars": 2208,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/helm/release_routes.go",
    "chars": 8659,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/helm/respository_routes.go",
    "chars": 8003,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/plan/config_routes.go",
    "chars": 2444,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/plan/node_routes.go",
    "chars": 2823,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/plan/plan.go",
    "chars": 2227,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/plan/plan_routes.go",
    "chars": 4572,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/plan/task_routes.go",
    "chars": 1797,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/proxy/helper.go",
    "chars": 801,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/proxy/proxy.go",
    "chars": 2505,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/router.go",
    "chars": 2208,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/static/index.html",
    "chars": 1099,
    "preview": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-wi"
  },
  {
    "path": "api/server/router/tenant/tenant.go",
    "chars": 1235,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/tenant/tenant_routes.go",
    "chars": 2568,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/user/user.go",
    "chars": 1404,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/router/user/user_routes.go",
    "chars": 7332,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/validator/helper.go",
    "chars": 933,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/validator/password.go",
    "chars": 1119,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/validator/rbac.go",
    "chars": 1636,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "api/server/validator/validator.go",
    "chars": 2182,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "cmd/app/config/config.go",
    "chars": 2773,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "cmd/app/options/options.go",
    "chars": 6793,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "cmd/app/server.go",
    "chars": 3635,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "cmd/pixiuserver.go",
    "chars": 1638,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "config.yaml",
    "chars": 970,
    "preview": "default:\n  # 运行模式,可选 debug 和 release\n  mode: debug\n  # 服务监听端口\n  listen: 8091\n  # jwt 签名的 key\n  jwt_key: pixiu\n  # 自动创建指定"
  },
  {
    "path": "deploy/README.md",
    "chars": 729,
    "preview": "# Pixiu\n\nPixiu是貔貅的服务端, 貔貅是一个广泛使用的、具有web-ui的、实现多集群管理的、非常好用的kubernetes(k8s)容器管理平台.\n\n本 chart 使用 [Helm](https://helm.sh) 包管理"
  },
  {
    "path": "deploy/pixiu/.helmignore",
    "chars": 349,
    "preview": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation"
  },
  {
    "path": "deploy/pixiu/Chart.yaml",
    "chars": 1141,
    "preview": "apiVersion: v2\nname: pixiu\ndescription: A Helm chart for Kubernetes\n\n# A chart can be either an 'application' or a 'libr"
  },
  {
    "path": "deploy/pixiu/templates/NOTES.txt",
    "chars": 1739,
    "preview": "1. Get the application URL by running these commands:\n{{- if .Values.ingress.enabled }}\n{{- range $host := .Values.ingre"
  },
  {
    "path": "deploy/pixiu/templates/_helpers.tpl",
    "chars": 1762,
    "preview": "{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"pixiu.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc"
  },
  {
    "path": "deploy/pixiu/templates/configmap.yaml",
    "chars": 1791,
    "preview": "# Copyright 2021 The Pixiu Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
  },
  {
    "path": "deploy/pixiu/templates/deployment.yaml",
    "chars": 2125,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"pixiu.fullname\" . }}\n  labels:\n    {{- include \"pixiu"
  },
  {
    "path": "deploy/pixiu/templates/hpa.yaml",
    "chars": 910,
    "preview": "{{- if .Values.autoscaling.enabled }}\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: {{"
  },
  {
    "path": "deploy/pixiu/templates/ingress.yaml",
    "chars": 1052,
    "preview": "{{- if .Values.ingress.enabled -}}\n{{- $fullName := include \"pixiu.fullname\" . -}}\n{{- $svcPort := .Values.service.port "
  },
  {
    "path": "deploy/pixiu/templates/service.yaml",
    "chars": 355,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"pixiu.fullname\" . }}\n  labels:\n    {{- include \"pixiu.labels\""
  },
  {
    "path": "deploy/pixiu/templates/serviceaccount.yaml",
    "chars": 316,
    "preview": "{{- if .Values.serviceAccount.create -}}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ include \"pixiu.service"
  },
  {
    "path": "deploy/pixiu/values.yaml",
    "chars": 2342,
    "preview": "# Default values for pixiu.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\ndefa"
  },
  {
    "path": "docker/Dockerfile",
    "chars": 644,
    "preview": "FROM golang:1.17-alpine as builder\nWORKDIR /app\nARG VERSION\nENV GOPROXY=https://goproxy.cn\nCOPY ../go.mod ./\nCOPY ../go."
  },
  {
    "path": "docker/Dockerfile-toolbox",
    "chars": 1323,
    "preview": "# 使用 Ubuntu 作为基础镜像\nFROM ubuntu:22.04\n\nARG K8S_VERSION\nARG HELM_VERSION\n\n# 安装vim\nRUN apt-get update && apt-get install -y"
  },
  {
    "path": "docker/start.sh",
    "chars": 392,
    "preview": "#!/bin/sh\nset -o errexit\nset -o xtrace\n\nif [[ ! -d \"/etc/pixiu\" ]]; then\n    mkdir -p /etc/pixiu\nfi\n\nif [[ -e \"/static/c"
  },
  {
    "path": "docs/OWNERS",
    "chars": 26,
    "preview": "reviewers:\n  - caoyingjun\n"
  },
  {
    "path": "docs/README.md",
    "chars": 203,
    "preview": "# Pixiu\n\n### 初始账号\n```shell\npixiu/Pixiu123456!\n```\n\n### 主进程启动\n```shell\ngo run cmd/pixiuserver.go --configfile ./config.ya"
  },
  {
    "path": "docs/apis.md",
    "chars": 1116,
    "preview": "# Pixiu API Specification\n\n- Pixiu API 是对 Pixiu 资源的调用接口,通常接口有 list, show details, create, update 和 delete, 以及对 resource "
  },
  {
    "path": "docs/sql.md",
    "chars": 5834,
    "preview": "# 创建 `pixiu` 数据库\n```sql\nCREATE DATABASE pixiu;\n```\n\n## 创建 `clusters` 表\n```sql\nCREATE TABLE `clusters` (\n    id int prima"
  },
  {
    "path": "go.mod",
    "chars": 9420,
    "preview": "module github.com/caoyingjunz/pixiu\n\ngo 1.17\n\nrequire (\n\tgithub.com/bmatcuk/doublestar/v4 v4.6.1\n\tgithub.com/caoyingjunz"
  },
  {
    "path": "go.sum",
    "chars": 215830,
    "preview": "bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=\nbazil.org/fuse "
  },
  {
    "path": "hack/tools/licfmt/licfmt.go",
    "chars": 6479,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "hack/update-gofmt.sh",
    "chars": 700,
    "preview": "#!/bin/bash\n\n# Copyright 2021 The Pixiu Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# y"
  },
  {
    "path": "hack/update-image.sh",
    "chars": 345,
    "preview": "#!/bin/bash\nfunction update() {\n    docker ccr.ccs.tencentyun.com/pixiucloud/pixiu-aio:latest\n    docker rm -f pixiu-aio"
  },
  {
    "path": "hack/verify-gofmt.sh",
    "chars": 1054,
    "preview": "#!/bin/bash\n\n# Copyright 2021 The Pixiu Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# y"
  },
  {
    "path": "install.md",
    "chars": 1574,
    "preview": "# 前置准备\n```bash\n确保 docker 已经安装\n```\n# 数据库\n```bash\n# 选择1:直接提供可用数据库\n\n# 选择2:快速启动数据库\ndocker run -d --net host --restart=always"
  },
  {
    "path": "pkg/client/cache.go",
    "chars": 5008,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/client/client.go",
    "chars": 1553,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/client/helm.go",
    "chars": 2374,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/client/task.go",
    "chars": 3649,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
  },
  {
    "path": "pkg/client/token_cache.go",
    "chars": 1265,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/client/user_cache.go",
    "chars": 1218,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/audit/audit.go",
    "chars": 4061,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/auth/auth.go",
    "chars": 8617,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/cluster/cluster.go",
    "chars": 29012,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/cluster/informer.go",
    "chars": 7867,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/cluster/util.go",
    "chars": 2428,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/cluster/ws.go",
    "chars": 3491,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/controller.go",
    "chars": 2168,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/helm/helm.go",
    "chars": 2341,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/helm/releases.go",
    "chars": 6081,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/helm/repository.go",
    "chars": 5816,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/bootstrap_servers.go",
    "chars": 1202,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/checker.go",
    "chars": 766,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/deploy.go",
    "chars": 1699,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/plan.go",
    "chars": 13012,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/plan_config.go",
    "chars": 5529,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/plan_node.go",
    "chars": 6197,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/plan_task.go",
    "chars": 4211,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/register.go",
    "chars": 3683,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/render.go",
    "chars": 5547,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/plan/worker.go",
    "chars": 6496,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/tenant/tenant.go",
    "chars": 4054,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/user/user.go",
    "chars": 10426,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/user/user_test.go",
    "chars": 579,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/controller/util/util.go",
    "chars": 4230,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/audit.go",
    "chars": 2502,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/cluster.go",
    "chars": 5134,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/factory.go",
    "chars": 1598,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/logger.go",
    "chars": 1892,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/migrator.go",
    "chars": 1198,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/audit.go",
    "chars": 2962,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/cluster.go",
    "chars": 2034,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/model.go",
    "chars": 840,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/pixiu/model.go",
    "chars": 1145,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/plan.go",
    "chars": 2408,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/rbac.go",
    "chars": 5742,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/rbac_test.go",
    "chars": 6140,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/repository.go",
    "chars": 2201,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/tenant.go",
    "chars": 965,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/model/user.go",
    "chars": 1453,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/options.go",
    "chars": 3519,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/plan.go",
    "chars": 12453,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/repository.go",
    "chars": 3076,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/tenant.go",
    "chars": 3269,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/db/user.go",
    "chars": 3971,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/jobmanager/audit_cleaner.go",
    "chars": 1911,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/jobmanager/cluster_syncer.go",
    "chars": 4518,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/jobmanager/context.go",
    "chars": 1089,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/jobmanager/manager.go",
    "chars": 1388,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/static/localfile.go",
    "chars": 1422,
    "preview": "/*\nCopyright 2025 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/static/static.go",
    "chars": 1639,
    "preview": "/*\nCopyright 2025 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/types/helm.go",
    "chars": 1854,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/types/meta.go",
    "chars": 9063,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/types/request.go",
    "chars": 9162,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/types/types.go",
    "chars": 10732,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/container/container.go",
    "chars": 4884,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/errors/errors.go",
    "chars": 2248,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/log/log.go",
    "chars": 3019,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/lru/lru.go",
    "chars": 1855,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/ssh/ssh.go",
    "chars": 1165,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/token/token.go",
    "chars": 1845,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/util.go",
    "chars": 3456,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/util_test.go",
    "chars": 3829,
    "preview": "/*\nCopyright 2024 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "pkg/util/uuid/uuid.go",
    "chars": 943,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use th"
  },
  {
    "path": "template/globals.go",
    "chars": 1413,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "template/hosts.go",
    "chars": 792,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  },
  {
    "path": "template/multinode.go",
    "chars": 2273,
    "preview": "/*\nCopyright 2021 The Pixiu Authors.\n\nLicensed under the Apache License, Version 2.0 (phe \"License\");\nyou may not use th"
  }
]

About this extraction

This page contains the full source code of the caoyingjunz/gopixiu GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 158 files (746.1 KB), approximately 266.4k tokens, and a symbol index with 1054 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!