Initial commit
This commit is contained in:
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
tmp/
|
||||
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
pkg/cmd/api/spec/api.swagger.json linguist-generated=true
|
||||
pkg/cmd/api/spec/static.go linguist-generated=true
|
||||
16
.github/.stale.yaml
vendored
Normal file
16
.github/.stale.yaml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 30
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 14
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- lifecycle/frozen
|
||||
staleLabel: lifecycle/stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Any further update will
|
||||
cause the issue/pull request to no longer be considered stale. Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue is being automatically closed due to inactivity.
|
||||
42
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
42
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
---
|
||||
|
||||
|
||||
**General remarks**
|
||||
|
||||
> Please delete this section including header before submitting
|
||||
> 也可以使用中文
|
||||
>
|
||||
> This form is to report bugs. For general usage questions refer to our Slack channel
|
||||
> [KubeSphere-users](https://join.slack.com/t/kubesphere/shared_invite/enQtNTE3MDIxNzUxNzQ0LTdkNTc3OTdmNzdiODViZjViNTU5ZDY3M2I2MzY4MTI4OGZlOTJmMDg5ZTFiMDAwYzNlZDY5NjA0NzZlNDU5NmY)
|
||||
|
||||
**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的版本)**
|
||||
KubeSphere:
|
||||
Kubernetes: (If KubeSphere installer used, you can skip this)
|
||||
|
||||
|
||||
**Environment(环境的硬件配置)**
|
||||
How many nodes and their hardware configuration:
|
||||
|
||||
For example:
|
||||
3 masters: 8cpu/8g
|
||||
3 nodes: 8cpu/16g
|
||||
|
||||
(and other info are welcomed to help us debugging)
|
||||
|
||||
**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.
|
||||
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Files generated by JetBrains IDEs, e.g. IntelliJ IDEA
|
||||
.idea/
|
||||
*.iml
|
||||
bin/
|
||||
|
||||
# Vscode files
|
||||
.vscode/
|
||||
|
||||
tmp/
|
||||
|
||||
# OSX trash
|
||||
.DS_Store
|
||||
30
.travis.yml
Normal file
30
.travis.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
- docker
|
||||
|
||||
language: go
|
||||
|
||||
git:
|
||||
depth: false
|
||||
|
||||
go:
|
||||
- 1.10
|
||||
|
||||
go_import_path: kubesphere.io/kubesphere
|
||||
|
||||
before_install:
|
||||
- curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
|
||||
before_script:
|
||||
- dep ensure -v
|
||||
- docker --version
|
||||
- dep ensure -v
|
||||
|
||||
script:
|
||||
- make fmt-check && make build
|
||||
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
provider: script
|
||||
script: bash install/scripts/docker_push
|
||||
on:
|
||||
branch: master
|
||||
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM golang:1.10.3 as builder
|
||||
|
||||
# Copy in the go src
|
||||
WORKDIR /go/src/kubesphere.io/kubesphere
|
||||
COPY pkg/ pkg/
|
||||
COPY cmd/ cmd/
|
||||
COPY vendor/ vendor/
|
||||
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o ks-apiserver kubesphere.io/kubesphere/cmd/ks-apiserver
|
||||
|
||||
|
||||
FROM alpine:3.6
|
||||
WORKDIR /
|
||||
COPY --from=builder /go/src/kubesphere.io/kubesphere/ks-apiserver .
|
||||
COPY ./install/ingress-controller /etc/kubesphere/ingress-controller
|
||||
COPY ./install/swagger-ui /usr/lib/kubesphere/swagger-ui
|
||||
CMD ["ks-apiserver"]
|
||||
816
Gopkg.lock
generated
Normal file
816
Gopkg.lock
generated
Normal file
@@ -0,0 +1,816 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "cloud.google.com/go"
|
||||
packages = ["compute/metadata"]
|
||||
revision = "c9474f2f8deb81759839474b6bd1726bbfe1c1c4"
|
||||
version = "v0.36.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Microsoft/go-winio"
|
||||
packages = ["."]
|
||||
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
|
||||
version = "v0.4.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/PuerkitoBio/purell"
|
||||
packages = ["."]
|
||||
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/PuerkitoBio/urlesc"
|
||||
packages = ["."]
|
||||
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||
version = "v1.0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/beorn7/perks"
|
||||
packages = ["quantile"]
|
||||
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/docker/distribution"
|
||||
packages = [
|
||||
"digestset",
|
||||
"reference"
|
||||
]
|
||||
revision = "749f6afb4572201e3c37325d0ffedb6f32be8950"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/docker"
|
||||
packages = [
|
||||
"api",
|
||||
"api/types",
|
||||
"api/types/blkiodev",
|
||||
"api/types/container",
|
||||
"api/types/events",
|
||||
"api/types/filters",
|
||||
"api/types/image",
|
||||
"api/types/mount",
|
||||
"api/types/network",
|
||||
"api/types/registry",
|
||||
"api/types/strslice",
|
||||
"api/types/swarm",
|
||||
"api/types/time",
|
||||
"api/types/versions",
|
||||
"api/types/volume",
|
||||
"client",
|
||||
"pkg/ioutils",
|
||||
"pkg/longpath",
|
||||
"pkg/system",
|
||||
"pkg/tlsconfig"
|
||||
]
|
||||
revision = "90d35abf7b3535c1c319c872900fbd76374e521c"
|
||||
version = "v17.05.0-ce-rc3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/docker/go-connections"
|
||||
packages = [
|
||||
"nat",
|
||||
"sockets",
|
||||
"tlsconfig"
|
||||
]
|
||||
revision = "7395e3f8aa162843a74ed6d48e79627d9792ac55"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/go-units"
|
||||
packages = ["."]
|
||||
revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
|
||||
version = "v0.3.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/docker/libtrust"
|
||||
packages = ["."]
|
||||
revision = "aabc10ec26b754e797f9028f4589c5b7bd90dc20"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/emicklei/go-restful"
|
||||
packages = [
|
||||
".",
|
||||
"log"
|
||||
]
|
||||
revision = "3658237ded108b4134956c1b3050349d93e7b895"
|
||||
version = "v2.7.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/emicklei/go-restful-openapi"
|
||||
packages = ["."]
|
||||
revision = "51bf251d405ad1e23511fef0a2dbe40bc70ce2c6"
|
||||
version = "v0.11.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/ghodss/yaml"
|
||||
packages = ["."]
|
||||
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-logr/logr"
|
||||
packages = ["."]
|
||||
revision = "9fb12b3b21c5415d16ac18dc5cd42c1cfdd40c4e"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-logr/zapr"
|
||||
packages = ["."]
|
||||
revision = "7536572e8d55209135cd5e7ccf7fce43dca217ab"
|
||||
version = "v0.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/jsonpointer"
|
||||
packages = ["."]
|
||||
revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/jsonreference"
|
||||
packages = ["."]
|
||||
revision = "3fb327e6747da3043567ee86abd02bb6376b6be2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/spec"
|
||||
packages = ["."]
|
||||
revision = "bce47c9386f9ecd6b86f450478a80103c3fe1402"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/swag"
|
||||
packages = ["."]
|
||||
revision = "2b0bd4f193d011c203529df626a65d63cb8a79e8"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
packages = ["."]
|
||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"sortkeys"
|
||||
]
|
||||
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
packages = ["."]
|
||||
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/groupcache"
|
||||
packages = ["lru"]
|
||||
revision = "5b532d6fd5efaf7fa130d4e859a2fde0fc3a9e1b"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"ptypes",
|
||||
"ptypes/any",
|
||||
"ptypes/duration",
|
||||
"ptypes/timestamp"
|
||||
]
|
||||
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/btree"
|
||||
packages = ["."]
|
||||
revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/gofuzz"
|
||||
packages = ["."]
|
||||
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/google/uuid"
|
||||
packages = ["."]
|
||||
revision = "9b3b1e0f5f99ae461456d768e7d301a7acdaa2d8"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/googleapis/gnostic"
|
||||
packages = [
|
||||
"OpenAPIv2",
|
||||
"compiler",
|
||||
"extensions"
|
||||
]
|
||||
revision = "7c663266750e7d82587642f65e60bc4083f1f84e"
|
||||
version = "v0.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gregjones/httpcache"
|
||||
packages = [
|
||||
".",
|
||||
"diskcache"
|
||||
]
|
||||
revision = "3befbb6ad0cc97d4c25d851e9528915809e1a22f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/golang-lru"
|
||||
packages = [
|
||||
".",
|
||||
"simplelru"
|
||||
]
|
||||
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/imdario/mergo"
|
||||
packages = ["."]
|
||||
revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58"
|
||||
version = "v0.3.5"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/inconshreveable/mousetrap"
|
||||
packages = ["."]
|
||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jinzhu/gorm"
|
||||
packages = ["."]
|
||||
revision = "6ed508ec6a4ecb3531899a69cbc746ccf65a4166"
|
||||
version = "v1.9.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/jinzhu/inflection"
|
||||
packages = ["."]
|
||||
revision = "04140366298a54a039076d798123ffa108fff46c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/json-iterator/go"
|
||||
packages = ["."]
|
||||
revision = "5bc93205020f6311d7e4a34f82c5616a18ec35e5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mailru/easyjson"
|
||||
packages = [
|
||||
"buffer",
|
||||
"jlexer",
|
||||
"jwriter"
|
||||
]
|
||||
revision = "3fdea8d05856a0c8df22ed4bc71b3219245e4485"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mattbaird/jsonpatch"
|
||||
packages = ["."]
|
||||
revision = "81af80346b1a01caae0cbc27fd3c1ba5b11e189f"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
packages = ["pbutil"]
|
||||
revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mitchellh/go-homedir"
|
||||
packages = ["."]
|
||||
revision = "af06845cf3004701891bf4fdb884bfe4920b3727"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/modern-go/concurrent"
|
||||
packages = ["."]
|
||||
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
|
||||
version = "1.0.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/modern-go/reflect2"
|
||||
packages = ["."]
|
||||
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
|
||||
version = "1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/opencontainers/go-digest"
|
||||
packages = ["."]
|
||||
revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf"
|
||||
version = "v1.0.0-rc1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pborman/uuid"
|
||||
packages = ["."]
|
||||
revision = "adf5a7427709b9deb95d29d3fa8a2bf9cfd388f1"
|
||||
version = "v1.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/petar/GoLLRB"
|
||||
packages = ["llrb"]
|
||||
revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/peterbourgon/diskv"
|
||||
packages = ["."]
|
||||
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
|
||||
version = "v2.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
packages = [
|
||||
"prometheus",
|
||||
"prometheus/internal",
|
||||
"prometheus/promhttp"
|
||||
]
|
||||
revision = "505eaef017263e299324067d40ca2c48f6a2cf50"
|
||||
version = "v0.9.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/client_model"
|
||||
packages = ["go"]
|
||||
revision = "fd36f4220a901265f90734c3183c5f0c91daa0b8"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/prometheus/common"
|
||||
packages = [
|
||||
"expfmt",
|
||||
"internal/bitbucket.org/ww/goautoneg",
|
||||
"model"
|
||||
]
|
||||
revision = "cfeb6f9992ffa54aaa4f2170ade4067ee478b250"
|
||||
version = "v0.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/procfs"
|
||||
packages = [
|
||||
".",
|
||||
"internal/util",
|
||||
"iostats",
|
||||
"nfs",
|
||||
"xfs"
|
||||
]
|
||||
revision = "bbced9601137e764853b2fad7ec3e2dc4c504e02"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/cobra"
|
||||
packages = ["."]
|
||||
revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "go.uber.org/atomic"
|
||||
packages = ["."]
|
||||
revision = "1ea20fb1cbb1cc08cbd0d913a96dead89aa18289"
|
||||
version = "v1.3.2"
|
||||
|
||||
[[projects]]
|
||||
name = "go.uber.org/multierr"
|
||||
packages = ["."]
|
||||
revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "go.uber.org/zap"
|
||||
packages = [
|
||||
".",
|
||||
"buffer",
|
||||
"internal/bufferpool",
|
||||
"internal/color",
|
||||
"internal/exit",
|
||||
"zapcore"
|
||||
]
|
||||
revision = "ff33455a0e382e8a81d14dd7c922020b6b5e7982"
|
||||
version = "v1.9.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "7f39a6fea4fe9364fb61e1def6a268a51b4f3a06"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"context/ctxhttp",
|
||||
"http/httpguts",
|
||||
"http2",
|
||||
"http2/hpack",
|
||||
"idna",
|
||||
"internal/socks",
|
||||
"proxy"
|
||||
]
|
||||
revision = "db08ff08e8622530d9ed3a0e8ac279f6d4c02196"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [
|
||||
".",
|
||||
"google",
|
||||
"internal",
|
||||
"jws",
|
||||
"jwt"
|
||||
]
|
||||
revision = "9b3c75971fc92dd27c6436a37c05c831498658f1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "fc8bd948cf46f9c7af0f07d34151ce25fe90e477"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"collate",
|
||||
"collate/build",
|
||||
"internal/colltab",
|
||||
"internal/gen",
|
||||
"internal/tag",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"language",
|
||||
"secure/bidirule",
|
||||
"transform",
|
||||
"unicode/bidi",
|
||||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
"unicode/rangetable",
|
||||
"width"
|
||||
]
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/time"
|
||||
packages = ["rate"]
|
||||
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/tools"
|
||||
packages = ["container/intsets"]
|
||||
revision = "44bee7e801e4a70b5fc9a91ff23830ab4df55d5e"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [
|
||||
".",
|
||||
"cloudsql",
|
||||
"internal",
|
||||
"internal/app_identity",
|
||||
"internal/base",
|
||||
"internal/datastore",
|
||||
"internal/log",
|
||||
"internal/modules",
|
||||
"internal/remote_api",
|
||||
"internal/urlfetch",
|
||||
"urlfetch"
|
||||
]
|
||||
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/inf.v0"
|
||||
packages = ["."]
|
||||
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
|
||||
version = "v0.9.1"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||
version = "v2.2.1"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/api"
|
||||
packages = [
|
||||
"admission/v1beta1",
|
||||
"admissionregistration/v1alpha1",
|
||||
"admissionregistration/v1beta1",
|
||||
"apps/v1",
|
||||
"apps/v1beta1",
|
||||
"apps/v1beta2",
|
||||
"authentication/v1",
|
||||
"authentication/v1beta1",
|
||||
"authorization/v1",
|
||||
"authorization/v1beta1",
|
||||
"autoscaling/v1",
|
||||
"autoscaling/v2beta1",
|
||||
"autoscaling/v2beta2",
|
||||
"batch/v1",
|
||||
"batch/v1beta1",
|
||||
"batch/v2alpha1",
|
||||
"certificates/v1beta1",
|
||||
"coordination/v1beta1",
|
||||
"core/v1",
|
||||
"events/v1beta1",
|
||||
"extensions/v1beta1",
|
||||
"networking/v1",
|
||||
"policy/v1beta1",
|
||||
"rbac/v1",
|
||||
"rbac/v1alpha1",
|
||||
"rbac/v1beta1",
|
||||
"scheduling/v1alpha1",
|
||||
"scheduling/v1beta1",
|
||||
"settings/v1alpha1",
|
||||
"storage/v1",
|
||||
"storage/v1alpha1",
|
||||
"storage/v1beta1"
|
||||
]
|
||||
revision = "b503174bad5991eb66f18247f52e41c3258f6348"
|
||||
version = "kubernetes-1.12.3"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/apimachinery"
|
||||
packages = [
|
||||
"pkg/api/errors",
|
||||
"pkg/api/meta",
|
||||
"pkg/api/resource",
|
||||
"pkg/apis/meta/internalversion",
|
||||
"pkg/apis/meta/v1",
|
||||
"pkg/apis/meta/v1/unstructured",
|
||||
"pkg/apis/meta/v1beta1",
|
||||
"pkg/conversion",
|
||||
"pkg/conversion/queryparams",
|
||||
"pkg/fields",
|
||||
"pkg/labels",
|
||||
"pkg/runtime",
|
||||
"pkg/runtime/schema",
|
||||
"pkg/runtime/serializer",
|
||||
"pkg/runtime/serializer/json",
|
||||
"pkg/runtime/serializer/protobuf",
|
||||
"pkg/runtime/serializer/recognizer",
|
||||
"pkg/runtime/serializer/streaming",
|
||||
"pkg/runtime/serializer/versioning",
|
||||
"pkg/selection",
|
||||
"pkg/types",
|
||||
"pkg/util/cache",
|
||||
"pkg/util/clock",
|
||||
"pkg/util/diff",
|
||||
"pkg/util/errors",
|
||||
"pkg/util/framer",
|
||||
"pkg/util/intstr",
|
||||
"pkg/util/json",
|
||||
"pkg/util/mergepatch",
|
||||
"pkg/util/naming",
|
||||
"pkg/util/net",
|
||||
"pkg/util/rand",
|
||||
"pkg/util/runtime",
|
||||
"pkg/util/sets",
|
||||
"pkg/util/strategicpatch",
|
||||
"pkg/util/uuid",
|
||||
"pkg/util/validation",
|
||||
"pkg/util/validation/field",
|
||||
"pkg/util/wait",
|
||||
"pkg/util/yaml",
|
||||
"pkg/version",
|
||||
"pkg/watch",
|
||||
"third_party/forked/golang/json",
|
||||
"third_party/forked/golang/reflect"
|
||||
]
|
||||
revision = "eddba98df674a16931d2d4ba75edc3a389bf633a"
|
||||
version = "kubernetes-1.12.3"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/client-go"
|
||||
packages = [
|
||||
"discovery",
|
||||
"dynamic",
|
||||
"informers",
|
||||
"informers/admissionregistration",
|
||||
"informers/admissionregistration/v1alpha1",
|
||||
"informers/admissionregistration/v1beta1",
|
||||
"informers/apps",
|
||||
"informers/apps/v1",
|
||||
"informers/apps/v1beta1",
|
||||
"informers/apps/v1beta2",
|
||||
"informers/autoscaling",
|
||||
"informers/autoscaling/v1",
|
||||
"informers/autoscaling/v2beta1",
|
||||
"informers/autoscaling/v2beta2",
|
||||
"informers/batch",
|
||||
"informers/batch/v1",
|
||||
"informers/batch/v1beta1",
|
||||
"informers/batch/v2alpha1",
|
||||
"informers/certificates",
|
||||
"informers/certificates/v1beta1",
|
||||
"informers/coordination",
|
||||
"informers/coordination/v1beta1",
|
||||
"informers/core",
|
||||
"informers/core/v1",
|
||||
"informers/events",
|
||||
"informers/events/v1beta1",
|
||||
"informers/extensions",
|
||||
"informers/extensions/v1beta1",
|
||||
"informers/internalinterfaces",
|
||||
"informers/networking",
|
||||
"informers/networking/v1",
|
||||
"informers/policy",
|
||||
"informers/policy/v1beta1",
|
||||
"informers/rbac",
|
||||
"informers/rbac/v1",
|
||||
"informers/rbac/v1alpha1",
|
||||
"informers/rbac/v1beta1",
|
||||
"informers/scheduling",
|
||||
"informers/scheduling/v1alpha1",
|
||||
"informers/scheduling/v1beta1",
|
||||
"informers/settings",
|
||||
"informers/settings/v1alpha1",
|
||||
"informers/storage",
|
||||
"informers/storage/v1",
|
||||
"informers/storage/v1alpha1",
|
||||
"informers/storage/v1beta1",
|
||||
"kubernetes",
|
||||
"kubernetes/scheme",
|
||||
"kubernetes/typed/admissionregistration/v1alpha1",
|
||||
"kubernetes/typed/admissionregistration/v1beta1",
|
||||
"kubernetes/typed/apps/v1",
|
||||
"kubernetes/typed/apps/v1beta1",
|
||||
"kubernetes/typed/apps/v1beta2",
|
||||
"kubernetes/typed/authentication/v1",
|
||||
"kubernetes/typed/authentication/v1beta1",
|
||||
"kubernetes/typed/authorization/v1",
|
||||
"kubernetes/typed/authorization/v1beta1",
|
||||
"kubernetes/typed/autoscaling/v1",
|
||||
"kubernetes/typed/autoscaling/v2beta1",
|
||||
"kubernetes/typed/autoscaling/v2beta2",
|
||||
"kubernetes/typed/batch/v1",
|
||||
"kubernetes/typed/batch/v1beta1",
|
||||
"kubernetes/typed/batch/v2alpha1",
|
||||
"kubernetes/typed/certificates/v1beta1",
|
||||
"kubernetes/typed/coordination/v1beta1",
|
||||
"kubernetes/typed/core/v1",
|
||||
"kubernetes/typed/events/v1beta1",
|
||||
"kubernetes/typed/extensions/v1beta1",
|
||||
"kubernetes/typed/networking/v1",
|
||||
"kubernetes/typed/policy/v1beta1",
|
||||
"kubernetes/typed/rbac/v1",
|
||||
"kubernetes/typed/rbac/v1alpha1",
|
||||
"kubernetes/typed/rbac/v1beta1",
|
||||
"kubernetes/typed/scheduling/v1alpha1",
|
||||
"kubernetes/typed/scheduling/v1beta1",
|
||||
"kubernetes/typed/settings/v1alpha1",
|
||||
"kubernetes/typed/storage/v1",
|
||||
"kubernetes/typed/storage/v1alpha1",
|
||||
"kubernetes/typed/storage/v1beta1",
|
||||
"listers/admissionregistration/v1alpha1",
|
||||
"listers/admissionregistration/v1beta1",
|
||||
"listers/apps/v1",
|
||||
"listers/apps/v1beta1",
|
||||
"listers/apps/v1beta2",
|
||||
"listers/autoscaling/v1",
|
||||
"listers/autoscaling/v2beta1",
|
||||
"listers/autoscaling/v2beta2",
|
||||
"listers/batch/v1",
|
||||
"listers/batch/v1beta1",
|
||||
"listers/batch/v2alpha1",
|
||||
"listers/certificates/v1beta1",
|
||||
"listers/coordination/v1beta1",
|
||||
"listers/core/v1",
|
||||
"listers/events/v1beta1",
|
||||
"listers/extensions/v1beta1",
|
||||
"listers/networking/v1",
|
||||
"listers/policy/v1beta1",
|
||||
"listers/rbac/v1",
|
||||
"listers/rbac/v1alpha1",
|
||||
"listers/rbac/v1beta1",
|
||||
"listers/scheduling/v1alpha1",
|
||||
"listers/scheduling/v1beta1",
|
||||
"listers/settings/v1alpha1",
|
||||
"listers/storage/v1",
|
||||
"listers/storage/v1alpha1",
|
||||
"listers/storage/v1beta1",
|
||||
"pkg/apis/clientauthentication",
|
||||
"pkg/apis/clientauthentication/v1alpha1",
|
||||
"pkg/apis/clientauthentication/v1beta1",
|
||||
"pkg/version",
|
||||
"plugin/pkg/client/auth/exec",
|
||||
"plugin/pkg/client/auth/gcp",
|
||||
"rest",
|
||||
"rest/watch",
|
||||
"restmapper",
|
||||
"third_party/forked/golang/template",
|
||||
"tools/auth",
|
||||
"tools/cache",
|
||||
"tools/clientcmd",
|
||||
"tools/clientcmd/api",
|
||||
"tools/clientcmd/api/latest",
|
||||
"tools/clientcmd/api/v1",
|
||||
"tools/leaderelection",
|
||||
"tools/leaderelection/resourcelock",
|
||||
"tools/metrics",
|
||||
"tools/pager",
|
||||
"tools/record",
|
||||
"tools/reference",
|
||||
"transport",
|
||||
"util/buffer",
|
||||
"util/cert",
|
||||
"util/connrotation",
|
||||
"util/flowcontrol",
|
||||
"util/homedir",
|
||||
"util/integer",
|
||||
"util/jsonpath",
|
||||
"util/retry",
|
||||
"util/workqueue"
|
||||
]
|
||||
revision = "d082d5923d3cc0bfbb066ee5fbdea3d0ca79acf8"
|
||||
version = "kubernetes-1.12.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/component-base"
|
||||
packages = ["logs"]
|
||||
revision = "1925c57e3358154fd54383773de0c0c7710a9196"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/klog"
|
||||
packages = ["."]
|
||||
revision = "71442cd4037d612096940ceb0f3fec3f7fff66e0"
|
||||
version = "v0.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/kube-openapi"
|
||||
packages = ["pkg/util/proto"]
|
||||
revision = "d50a959ae76a85c7c262a9767ef29f37093c2b8a"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/kubernetes"
|
||||
packages = ["pkg/util/slice"]
|
||||
revision = "721bfa751924da8d1680787490c54b9179b1fed0"
|
||||
version = "v1.13.3"
|
||||
|
||||
[[projects]]
|
||||
name = "sigs.k8s.io/controller-runtime"
|
||||
packages = [
|
||||
"pkg/cache",
|
||||
"pkg/cache/internal",
|
||||
"pkg/client",
|
||||
"pkg/client/apiutil",
|
||||
"pkg/client/config",
|
||||
"pkg/internal/recorder",
|
||||
"pkg/leaderelection",
|
||||
"pkg/manager",
|
||||
"pkg/metrics",
|
||||
"pkg/patch",
|
||||
"pkg/recorder",
|
||||
"pkg/runtime/inject",
|
||||
"pkg/runtime/log",
|
||||
"pkg/runtime/signals",
|
||||
"pkg/webhook/admission",
|
||||
"pkg/webhook/admission/types",
|
||||
"pkg/webhook/internal/metrics",
|
||||
"pkg/webhook/types"
|
||||
]
|
||||
revision = "f6f0bc9611363b43664d08fb097ab13243ef621d"
|
||||
version = "v0.1.9"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "af7a1befccf91a9979c7710cf95e61ccb7dc4131fd0cc22e585e2e3b8034f92f"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
116
Gopkg.toml
Normal file
116
Gopkg.toml
Normal file
@@ -0,0 +1,116 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/docker/docker"
|
||||
version = "v17.05.0-ce"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/emicklei/go-restful"
|
||||
version = "2.7.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/emicklei/go-restful-swagger12"
|
||||
version = "1.0.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/spf13/pflag"
|
||||
version = "1.0.1"
|
||||
|
||||
[[override]]
|
||||
name = "gopkg.in/igm/sockjs-go.v2"
|
||||
version = "2.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
version = "2.2.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/api"
|
||||
version = "kubernetes-1.12.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/apimachinery"
|
||||
version = "kubernetes-1.12.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/client-go"
|
||||
version = "kubernetes-1.12.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/kubernetes"
|
||||
version = "1.12.3"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name="sigs.k8s.io/controller-runtime"
|
||||
version="v0.1.9"
|
||||
|
||||
[[override]]
|
||||
name="sigs.k8s.io/controller-tools"
|
||||
version="v0.1.9"
|
||||
|
||||
[[override]]
|
||||
name="k8s.io/component-base"
|
||||
branch="master"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
# To use reference package:
|
||||
# vendor/github.com/docker/docker/client/container_commit.go:17: undefined: reference.ParseNormalizedNamed
|
||||
# vendor/github.com/docker/docker/client/container_commit.go:25: undefined: reference.TagNameOnly
|
||||
# vendor/github.com/docker/docker/client/container_commit.go:30: undefined: reference.FamiliarNam
|
||||
[[override]]
|
||||
name = "github.com/docker/distribution"
|
||||
branch = "master"
|
||||
|
||||
# To use reference package:
|
||||
# vendor/github.com/docker/docker/registry/registry.go:30: cannot call non-function tlsconfig.ServerDefault (type tls.Config)
|
||||
# vendor/github.com/docker/docker/registry/registry.go:66: undefined: tlsconfig.SystemCertPool
|
||||
# vendor/github.com/docker/docker/registry/registry.go:168: cannot call non-function tlsconfig.ServerDefault (type tls.Config)
|
||||
# vendor/github.com/docker/docker/registry/service_v2.go:11: cannot call non-function tlsconfig.ServerDefault (type tls.Config)
|
||||
[[override]]
|
||||
name = "github.com/docker/go-connections"
|
||||
branch = "master"
|
||||
|
||||
# To use reference package:
|
||||
# vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go:104:3: unknown field 'CaseSensitive' in struct literal of type jsoniter.Config
|
||||
[[override]]
|
||||
name = "github.com/json-iterator/go"
|
||||
branch = "master"
|
||||
|
||||
|
||||
# For dependency below: Refer to issue https://github.com/golang/dep/issues/1799
|
||||
[[override]]
|
||||
name = "gopkg.in/fsnotify.v1"
|
||||
source = "https://github.com/fsnotify/fsnotify.git"
|
||||
version="v1.4.7"
|
||||
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
75
Makefile
Normal file
75
Makefile
Normal file
@@ -0,0 +1,75 @@
|
||||
# Copyright 2018 The KubeSphere Authors. All rights reserved.
|
||||
# Use of this source code is governed by a Apache license
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
# The binary to build
|
||||
BIN ?= ks-apiserver
|
||||
|
||||
IMG ?= kubespheredev/ks-apiserver
|
||||
OUTPUT_DIR=bin
|
||||
|
||||
define get_diff_files
|
||||
$(eval DIFF_FILES=$(shell git diff --name-only --diff-filter=ad | grep -E "^(test|cmd|pkg)/.+\.go"))
|
||||
endef
|
||||
define get_build_flags
|
||||
$(eval SHORT_VERSION=$(shell git describe --tags --always --dirty="-dev"))
|
||||
$(eval SHA1_VERSION=$(shell git show --quiet --pretty=format:%H))
|
||||
$(eval DATE=$(shell date +'%Y-%m-%dT%H:%M:%S'))
|
||||
$(eval BUILD_FLAG= -X $(TRAG.Version).ShortVersion="$(SHORT_VERSION)" \
|
||||
-X $(TRAG.Version).GitSha1Version="$(SHA1_VERSION)" \
|
||||
-X $(TRAG.Version).BuildDate="$(DATE)")
|
||||
endef
|
||||
|
||||
define ALL_HELP_INFO
|
||||
# Build code.
|
||||
#
|
||||
# Args:
|
||||
# WHAT: Directory names to build. If any of these directories has a 'main'
|
||||
# package, the build will produce executable files under $(OUT_DIR).
|
||||
# If not specified, "everything" will be built.
|
||||
# GOFLAGS: Extra flags to pass to 'go' when building.
|
||||
# GOLDFLAGS: Extra linking flags passed to 'go' when building.
|
||||
# GOGCFLAGS: Additional go compile flags passed to 'go' when building.
|
||||
#
|
||||
# Example:
|
||||
# make
|
||||
# make all
|
||||
# make all WHAT=cmd/ks-apiserver
|
||||
# Note: Use the -N -l options to disable compiler optimizations an inlining.
|
||||
# Using these build options allows you to subsequently use source
|
||||
# debugging tools like delve.
|
||||
endef
|
||||
.PHONY: all
|
||||
all: ks-apiserver test
|
||||
|
||||
# Build ks-apiserver binary
|
||||
ks-apiserver: generate fmt vet
|
||||
hack/gobuild.sh cmd/ks-apiserver
|
||||
|
||||
# Run go fmt against code
|
||||
fmt:
|
||||
go fmt ./pkg/... ./cmd/...
|
||||
|
||||
# Run go vet against code
|
||||
vet:
|
||||
go vet ./pkg/... ./cmd/...
|
||||
|
||||
# Generate code
|
||||
generate:
|
||||
ifndef GOPATH
|
||||
$(error GOPATH not defined, please define GOPATH. Run "go help gopath" to learn more about GOPATH)
|
||||
endif
|
||||
go generate ./pkg/... ./cmd/...
|
||||
|
||||
# Build the docker image
|
||||
docker-build: test
|
||||
docker build . -t ${IMG}
|
||||
|
||||
# Run tests
|
||||
test: generate fmt vet
|
||||
go test ./pkg/... ./cmd/... -coverprofile cover.out
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-make -C ./pkg/version clean
|
||||
@echo "ok"
|
||||
3
PROJECT
Normal file
3
PROJECT
Normal file
@@ -0,0 +1,3 @@
|
||||
version: "1"
|
||||
domain: kubesphere.io
|
||||
repo: kubesphere.io/kubesphere
|
||||
37
README.md
Normal file
37
README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# KubeSphere
|
||||
[](https://github.com/KubeSphere/KubeSphere/blob/master/LICENSE)
|
||||
[](https://travis-ci.org/kubesphere/kubesphere)
|
||||
|
||||
----
|
||||
***KubeSphere*** is a distribution of [Kubernetes](https://kubernetes.io), aimed to provide quick setup, friendly and easily use, and powerful management features for Kubernetes clusters, which could help both personal and enterprise users, reduce their learning curve of Kubernetes, accelerate their transform process from other container platforms to Kubernetes.
|
||||
|
||||
**Features:**
|
||||
- Multiple IaaS platform support, including baremetal/KVM/QingCloud, and more will be supported in future release.
|
||||
- Easy setup of Kubernetes standalone(only one master node) and cluster environment(including High Availability support).
|
||||
- Powerful management console to help business users to manage and monitor the Kubernetes.
|
||||
- Integrate with [OpenPitrix](https://github.com/openpitrix) to provide full life cycle of application management and be compatible of helm package.
|
||||
- Support popular open source network solutions, including calico and flannel, also could use [qingcloud hostnic solution](https://github.com/yunify/hostnic-cni) if the Kubernetes is deployed on QingCloud platform.
|
||||
- Support popular open source storage solutions, including Glusterfs and Cephfs, also could use [qingcloud storage solution](https://github.com/yunify/qingcloud-csi) or [qingstor storage solution](https://github.com/yunify/qingstor-csi) if the Kubernetes is deployed on QingCloud platform or QingStor NeonSAN.
|
||||
- CI/CD support.
|
||||
- Service Mesh support.
|
||||
- Multiple image registries support.
|
||||
- Integrate with QingCloud IAM.
|
||||
----
|
||||
|
||||
## Motivation
|
||||
|
||||
The project originates from the requirement and pains we heard from our customers on public and private QingCloud platform, who have strong will to deploy Kubernetes in their IT system but struggle on completed setup process and long learning curve. With help of KubeSphere, their IT operators could setup Kubernetes environment quickly and use an easy management UI interface to mange their applications, also KubeSphere provides more features to help customers to handle daily business more easily, including CI/CD, micro services management...etc.
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
**TBD**
|
||||
|
||||
## Design
|
||||
|
||||
## Contributing to the project
|
||||
|
||||
All members of the KubeSphere community must abide by [Code of Conduct](docs/code-of-conduct.md). Only by respecting each other can we develop a productive, collaborative community.
|
||||
|
||||
You can then find out more detail [here](docs/welcome-toKubeSphere-new-developer-guide.md).
|
||||
|
||||
|
||||
3
build/builder-docker/.ash_history
Normal file
3
build/builder-docker/.ash_history
Normal file
@@ -0,0 +1,3 @@
|
||||
ls /go/bin
|
||||
go version
|
||||
exit
|
||||
19
build/builder-docker/Dockerfile
Normal file
19
build/builder-docker/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright 2018 The KubeSphere Authors. All rights reserved.
|
||||
# Use of this source code is governed by a Apache license
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
FROM golang:1.10.2-alpine3.7 as builder
|
||||
|
||||
RUN apk add --no-cache git curl openssl
|
||||
|
||||
RUN go get github.com/tools/godep
|
||||
#RUN go get github.com/emicklei/go-restful
|
||||
#RUN go get github.com/golang/glog
|
||||
#RUN go get github.com/spf13/pflag
|
||||
RUN go get golang.org/x/tools/cmd/goimports
|
||||
|
||||
FROM golang:1.10.2-alpine3.7
|
||||
|
||||
RUN apk add --no-cache git make curl openssl jq rsync godep
|
||||
|
||||
COPY --from=builder /go/bin /go/bin
|
||||
17
build/builder-docker/Makefile
Normal file
17
build/builder-docker/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2018 The KubeSphere Authors. All rights reserved.
|
||||
# Use of this source code is governed by a Apache license
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
default:
|
||||
docker build -t kubesphere/kubesphere-builder .
|
||||
@echo "ok"
|
||||
|
||||
pull:
|
||||
docker pull kubesphere/kubesphere-builder
|
||||
@echo "ok"
|
||||
|
||||
run:
|
||||
docker run --rm -it -v `pwd`:/root kubesphere/kubesphere-builder
|
||||
|
||||
clean:
|
||||
@echo "ok"
|
||||
87
cmd/controller-manager/controller-manager.go
Normal file
87
cmd/controller-manager/controller-manager.go
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apis"
|
||||
"kubesphere.io/kubesphere/pkg/controller"
|
||||
"kubesphere.io/kubesphere/pkg/webhook"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var metricsAddr string
|
||||
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
|
||||
flag.Parse()
|
||||
logf.SetLogger(logf.ZapLogger(false))
|
||||
log := logf.Log.WithName("entrypoint")
|
||||
|
||||
// Get a config to talk to the apiserver
|
||||
log.Info("setting up client for manager")
|
||||
cfg, err := config.GetConfig()
|
||||
if err != nil {
|
||||
log.Error(err, "unable to set up client config")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create a new Cmd to provide shared dependencies and start components
|
||||
log.Info("setting up manager")
|
||||
mgr, err := manager.New(cfg, manager.Options{})
|
||||
if err != nil {
|
||||
log.Error(err, "unable to set up overall controller manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
log.Info("Registering Components.")
|
||||
|
||||
// Setup Scheme for all resources
|
||||
log.Info("setting up scheme")
|
||||
if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
|
||||
log.Error(err, "unable add APIs to scheme")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Setup all Controllers
|
||||
log.Info("Setting up controller")
|
||||
if err := controller.AddToManager(mgr); err != nil {
|
||||
log.Error(err, "unable to register controllers to the manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
log.Info("setting up webhooks")
|
||||
if err := webhook.AddToManager(mgr); err != nil {
|
||||
log.Error(err, "unable to register webhooks to the manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
controller.Run(signals.SetupSignalHandler())
|
||||
|
||||
// Start the Cmd
|
||||
log.Info("Starting the Cmd.")
|
||||
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
|
||||
log.Error(err, "unable to run the manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
22
cmd/ks-apiserver/apiserver.go
Normal file
22
cmd/ks-apiserver/apiserver.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"kubesphere.io/kubesphere/cmd/ks-apiserver/app"
|
||||
"os"
|
||||
|
||||
// Install apis
|
||||
_ "kubesphere.io/kubesphere/pkg/apis/metrics/install"
|
||||
_ "kubesphere.io/kubesphere/pkg/apis/operations/install"
|
||||
_ "kubesphere.io/kubesphere/pkg/apis/resources/install"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
cmd := app.NewAPIServerCommand()
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
67
cmd/ks-apiserver/app/options/options.go
Normal file
67
cmd/ks-apiserver/app/options/options.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/pflag"
|
||||
"os"
|
||||
)
|
||||
|
||||
type ServerRunOptions struct {
|
||||
|
||||
// server bind address
|
||||
BindAddress string
|
||||
|
||||
// insecure port number
|
||||
InsecurePort int
|
||||
|
||||
// secure port number
|
||||
SecurePort int
|
||||
|
||||
// OpenPitrix api gateway service url
|
||||
OpenPitrixAddress string
|
||||
|
||||
// database connection string in MySQL like
|
||||
// user:password@tcp(host)/dbname?charset=utf8&parseTime=True
|
||||
DatabaseConnectionString string
|
||||
|
||||
// tls cert file
|
||||
TlsCertFile string
|
||||
|
||||
// tls private key file
|
||||
TlsPrivateKey string
|
||||
|
||||
// host openapi doc
|
||||
ApiDoc bool
|
||||
|
||||
// kubeconfig file path
|
||||
KubeConfig string
|
||||
}
|
||||
|
||||
func NewServerRunOptions() *ServerRunOptions {
|
||||
// create default server run options
|
||||
s := ServerRunOptions{
|
||||
BindAddress: "0.0.0.0",
|
||||
InsecurePort: 9090,
|
||||
SecurePort: 0,
|
||||
OpenPitrixAddress: "openpitrix-api-gateway.openpitrix-system.svc",
|
||||
DatabaseConnectionString: "",
|
||||
TlsCertFile: "",
|
||||
TlsPrivateKey: "",
|
||||
ApiDoc: true,
|
||||
}
|
||||
|
||||
return &s
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
|
||||
fs.StringVar(&s.BindAddress, "bind-address", "0.0.0.0", "server bind address")
|
||||
fs.IntVar(&s.InsecurePort, "insecure-port", 9090, "insecure port number")
|
||||
fs.IntVar(&s.SecurePort, "secure-port", 0, "secure port number")
|
||||
fs.StringVar(&s.OpenPitrixAddress, "openpitrix", "openpitrix-api-gateway.openpitrix-system.svc", "openpitrix api gateway address")
|
||||
fs.StringVar(&s.DatabaseConnectionString, "database-connection", "", "database connection string")
|
||||
fs.StringVar(&s.TlsCertFile, "tls-cert-file", "", "tls cert file")
|
||||
fs.StringVar(&s.TlsPrivateKey, "tls-private-key", "", "tls private key")
|
||||
fs.BoolVar(&s.ApiDoc, "api-doc", true, "host OpenAPI doc")
|
||||
fs.StringVar(&s.KubeConfig, "kubeconfig", fmt.Sprintf("%s/.kube/config", os.Getenv("HOME")), "path to kubeconfig file")
|
||||
}
|
||||
73
cmd/ks-apiserver/app/server.go
Normal file
73
cmd/ks-apiserver/app/server.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"github.com/spf13/cobra"
|
||||
"kubesphere.io/kubesphere/cmd/ks-apiserver/app/options"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/filter"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/signals"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func NewAPIServerCommand() *cobra.Command {
|
||||
s := options.NewServerRunOptions()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "ks-apiserver",
|
||||
Long: `The KubeSphere API server validates and configures data
|
||||
for the api objects. The API Server services REST operations and provides the frontend to the
|
||||
cluster's shared state through which all other components interact.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
//s.AddFlags(cmd.Flags())
|
||||
|
||||
return Run(s)
|
||||
},
|
||||
}
|
||||
|
||||
s.AddFlags(cmd.Flags())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func Run(s *options.ServerRunOptions) error {
|
||||
|
||||
var err error
|
||||
|
||||
stopChan := signals.SetupSignalHandler()
|
||||
informers.SharedInformerFactory().Start(stopChan)
|
||||
informers.SharedInformerFactory().WaitForCacheSync(stopChan)
|
||||
log.Println("resources sync success")
|
||||
|
||||
container := runtime.Container
|
||||
container.Filter(filter.Logging)
|
||||
|
||||
if len(s.KubeConfig) > 0 {
|
||||
client.KubeConfigFile = s.KubeConfig
|
||||
}
|
||||
|
||||
if s.ApiDoc {
|
||||
config := restfulspec.Config{
|
||||
WebServices: container.RegisteredWebServices(),
|
||||
APIPath: "/apidoc.json",
|
||||
}
|
||||
container.Add(restfulspec.NewOpenAPIService(config))
|
||||
}
|
||||
|
||||
log.Printf("Server listening on %d.", s.InsecurePort)
|
||||
|
||||
if s.InsecurePort != 0 {
|
||||
err = http.ListenAndServe(fmt.Sprintf("%s:%d", s.BindAddress, s.InsecurePort), container)
|
||||
}
|
||||
|
||||
if s.SecurePort != 0 && len(s.TlsCertFile) > 0 && len(s.TlsPrivateKey) > 0 {
|
||||
err = http.ListenAndServeTLS(fmt.Sprintf("%s:%d", s.BindAddress, s.SecurePort), s.TlsCertFile, s.TlsPrivateKey, container)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
49
config/default/kustomization.yaml
Normal file
49
config/default/kustomization.yaml
Normal file
@@ -0,0 +1,49 @@
|
||||
# Adds namespace to all resources.
|
||||
namespace: t-system
|
||||
|
||||
# Value of this field is prepended to the
|
||||
# names of all resources, e.g. a deployment named
|
||||
# "wordpress" becomes "alices-wordpress".
|
||||
# Note that it should also match with the prefix (text before '-') of the namespace
|
||||
# field above.
|
||||
namePrefix: t-
|
||||
|
||||
# Labels to add to all resources and selectors.
|
||||
#commonLabels:
|
||||
# someName: someValue
|
||||
|
||||
# Each entry in this list must resolve to an existing
|
||||
# resource definition in YAML. These are the resource
|
||||
# files that kustomize reads, modifies and emits as a
|
||||
# YAML string, with resources separated by document
|
||||
# markers ("---").
|
||||
resources:
|
||||
- ../rbac/rbac_role.yaml
|
||||
- ../rbac/rbac_role_binding.yaml
|
||||
- ../manager/manager.yaml
|
||||
# Comment the following 3 lines if you want to disable
|
||||
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
|
||||
# which protects your /metrics endpoint.
|
||||
- ../rbac/auth_proxy_service.yaml
|
||||
- ../rbac/auth_proxy_role.yaml
|
||||
- ../rbac/auth_proxy_role_binding.yaml
|
||||
|
||||
patches:
|
||||
- manager_image_patch.yaml
|
||||
# Protect the /metrics endpoint by putting it behind auth.
|
||||
# Only one of manager_auth_proxy_patch.yaml and
|
||||
# manager_prometheus_metrics_patch.yaml should be enabled.
|
||||
- manager_auth_proxy_patch.yaml
|
||||
# If you want your controller-manager to expose the /metrics
|
||||
# endpoint w/o any authn/z, uncomment the following line and
|
||||
# comment manager_auth_proxy_patch.yaml.
|
||||
# Only one of manager_auth_proxy_patch.yaml and
|
||||
# manager_prometheus_metrics_patch.yaml should be enabled.
|
||||
#- manager_prometheus_metrics_patch.yaml
|
||||
|
||||
vars:
|
||||
- name: WEBHOOK_SECRET_NAME
|
||||
objref:
|
||||
kind: Secret
|
||||
name: webhook-server-secret
|
||||
apiVersion: v1
|
||||
24
config/default/manager_auth_proxy_patch.yaml
Normal file
24
config/default/manager_auth_proxy_patch.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
# This patch inject a sidecar container which is a HTTP proxy for the controller manager,
|
||||
# it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-rbac-proxy
|
||||
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.0
|
||||
args:
|
||||
- "--secure-listen-address=0.0.0.0:8443"
|
||||
- "--upstream=http://127.0.0.1:8080/"
|
||||
- "--logtostderr=true"
|
||||
- "--v=10"
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
name: https
|
||||
- name: manager
|
||||
args:
|
||||
- "--metrics-addr=127.0.0.1:8080"
|
||||
12
config/default/manager_image_patch.yaml
Normal file
12
config/default/manager_image_patch.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
# Change the value of image field below to your controller image URL
|
||||
- image: IMAGE_URL
|
||||
name: manager
|
||||
19
config/default/manager_prometheus_metrics_patch.yaml
Normal file
19
config/default/manager_prometheus_metrics_patch.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
# This patch enables Prometheus scraping for the manager pod.
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
prometheus.io/scrape: 'true'
|
||||
spec:
|
||||
containers:
|
||||
# Expose the prometheus metrics on default port
|
||||
- name: manager
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
83
config/manager/manager.yaml
Normal file
83
config/manager/manager.yaml
Normal file
@@ -0,0 +1,83 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
name: system
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: controller-manager-service
|
||||
namespace: system
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
spec:
|
||||
selector:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
ports:
|
||||
- port: 443
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
serviceName: controller-manager-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- /manager
|
||||
image: controller:latest
|
||||
imagePullPolicy: Always
|
||||
name: manager
|
||||
env:
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: SECRET_NAME
|
||||
value: $(WEBHOOK_SECRET_NAME)
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 30Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 20Mi
|
||||
ports:
|
||||
- containerPort: 9876
|
||||
name: webhook-server
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /tmp/cert
|
||||
name: cert
|
||||
readOnly: true
|
||||
terminationGracePeriodSeconds: 10
|
||||
volumes:
|
||||
- name: cert
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: webhook-server-secret
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: webhook-server-secret
|
||||
namespace: system
|
||||
13
config/rbac/auth_proxy_role.yaml
Normal file
13
config/rbac/auth_proxy_role.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: proxy-role
|
||||
rules:
|
||||
- apiGroups: ["authentication.k8s.io"]
|
||||
resources:
|
||||
- tokenreviews
|
||||
verbs: ["create"]
|
||||
- apiGroups: ["authorization.k8s.io"]
|
||||
resources:
|
||||
- subjectaccessreviews
|
||||
verbs: ["create"]
|
||||
12
config/rbac/auth_proxy_role_binding.yaml
Normal file
12
config/rbac/auth_proxy_role_binding.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: proxy-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: proxy-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: system
|
||||
20
config/rbac/auth_proxy_service.yaml
Normal file
20
config/rbac/auth_proxy_service.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
prometheus.io/port: "8443"
|
||||
prometheus.io/scheme: https
|
||||
prometheus.io/scrape: "true"
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
name: controller-manager-metrics-service
|
||||
namespace: system
|
||||
spec:
|
||||
ports:
|
||||
- name: https
|
||||
port: 8443
|
||||
targetPort: https
|
||||
selector:
|
||||
control-plane: controller-manager
|
||||
controller-tools.k8s.io: "1.0"
|
||||
6
doc.go
Normal file
6
doc.go
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017 The OpenPitrix Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package openpitrix provides the best Paas and Iaas platform.
|
||||
package kubesphere
|
||||
14
docs/code-of-conduct.md
Normal file
14
docs/code-of-conduct.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# KubeSphere Code of Conduct
|
||||
|
||||
KubeSphere follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
# Best practice of committing code
|
||||
Besides following above conduct from CNCF, we also hope every contributor in this project could help us to improve the quality of code, something you should know before checking in any new code:
|
||||
- As gopher, make sure you already read [the conduct of Go language](https://golang.org/conduct) and [the instruction of writting Go](https://golang.org/doc/effective_go.html).
|
||||
- Fork the project under your account and make the changes you want there.
|
||||
- Execute 'go fmt' for every piece of new code.
|
||||
- Every pulling request(PR) would be better constructed with only one commit, this could help code reviewer to go through your code efficiently, also helpful for every follower of this project to understand what happens in this PR. If you need to make any further code change to address the comments from reviewers, which means some new commits will be generated under this PR, you need to use 'git rebase' to combine those commits together.
|
||||
- Every PR should only solve one problem or provide one feature, don't put several different fixes into one PR.
|
||||
- At lease two code reviewers should involve into code reviewing process.
|
||||
- Please introduce new third-party packages as little as possible to reduce the vendor dependency of this project. For example, don't import a full unit converting package but only use one function from it. For this case, you'd better write that function by yourself.
|
||||
- more.
|
||||
6
docs/design/README.md
Normal file
6
docs/design/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Architecture
|
||||
|
||||
Basic idea is to decouple application repository and runtime environment. The runtime environment an application can run is by matching the labels of runtime environment and the selector of the repository where the application is from.
|
||||
|
||||
## Design key points:
|
||||
|
||||
99
docs/design/arch.dot
Normal file
99
docs/design/arch.dot
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright 2017 The OpenPitrix Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// dot -Tpng -o output.png input.dot
|
||||
|
||||
digraph G {
|
||||
rankdir = LR;
|
||||
|
||||
subgraph clusterClient {
|
||||
node [
|
||||
fixedsize = true,
|
||||
width = 1, height = 1,
|
||||
]
|
||||
WebUI [shape = doublecircle];
|
||||
MobileApp [shape = doublecircle];
|
||||
XClient [shape = doublecircle];
|
||||
}
|
||||
|
||||
WebUI -> ApiGateway[
|
||||
label = "rest api",
|
||||
dir = both,
|
||||
style = bold,
|
||||
];
|
||||
MobileApp -> ApiGateway[
|
||||
label = "rest api",
|
||||
dir = both,
|
||||
style = bold,
|
||||
];
|
||||
XClient -> ApiGateway[
|
||||
label = "rest api",
|
||||
dir = both,
|
||||
style = bold,
|
||||
];
|
||||
|
||||
subgraph clusterOpenpitrix {
|
||||
|
||||
// rest api gateway
|
||||
ApiGateway [shape = rect,
|
||||
fixedsize = true,
|
||||
width = 1.4, height = 6.2,
|
||||
];
|
||||
|
||||
// microservice
|
||||
subgraph clusterServices {
|
||||
node [
|
||||
shape=record,
|
||||
fixedsize = true,
|
||||
width = 2.6, height = 1.3,
|
||||
];
|
||||
Cluster [shape = Mrecord];
|
||||
Runtime [shape = Mrecord,
|
||||
label="Runtime |{ plugin |{k8s|QingCloud|Other} }"
|
||||
];
|
||||
App [shape = Mrecord];
|
||||
Repo [shape = Mrecord];
|
||||
}
|
||||
|
||||
// service database
|
||||
subgraph clusterDB {
|
||||
node [
|
||||
fixedsize = true,
|
||||
width = 2.6, height = 1.3,
|
||||
];
|
||||
RepoDB [shape = cylinder];
|
||||
AppDB [shape = cylinder];
|
||||
RuntimeDB [shape = cylinder];
|
||||
ClusterDB [shape = cylinder];
|
||||
}
|
||||
|
||||
// api gateway
|
||||
ApiGateway -> Cluster [
|
||||
label = "grpc",
|
||||
dir = both,
|
||||
style = bold,
|
||||
];
|
||||
ApiGateway -> Repo [
|
||||
label = "grpc",
|
||||
dir = both,
|
||||
style = bold,
|
||||
];
|
||||
ApiGateway -> App [
|
||||
label = "grpc",
|
||||
dir = both,
|
||||
style = bold,
|
||||
];
|
||||
ApiGateway -> Runtime [
|
||||
label = "grpc",
|
||||
dir = both,
|
||||
style = bold,
|
||||
];
|
||||
|
||||
Repo -> RepoDB [label="SQL"];
|
||||
App -> AppDB [label="SQL"];
|
||||
Runtime -> RuntimeDB [label="SQL"];
|
||||
Cluster -> ClusterDB [label="SQL"];
|
||||
}
|
||||
}
|
||||
|
||||
BIN
docs/images/arch.png
Normal file
BIN
docs/images/arch.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/images/kubernetes.png
Normal file
BIN
docs/images/kubernetes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 551 KiB |
BIN
docs/images/logo.png
Normal file
BIN
docs/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
BIN
docs/images/openvpn.png
Normal file
BIN
docs/images/openvpn.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 399 KiB |
57
docs/prereqs.md
Normal file
57
docs/prereqs.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Developing for KubeSphere [deprecated]
|
||||
|
||||
This document is intended to be the canonical source of truth for things like
|
||||
supported toolchain versions for building KubeSphere.
|
||||
If you find a requirement that this doc does not capture, or if you find other
|
||||
docs with references to requirements that are not simply links to this doc,
|
||||
please [submit an issue](https://github.com/kubesphere/kubesphere/issues/new).
|
||||
|
||||
This document is intended to be relative to the branch in which it is found.
|
||||
It is guaranteed that requirements will change over time for the development
|
||||
branch, but release branches should not change.
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Setting up Go](#setting-up-go)
|
||||
- [To start developing KubeSphere](#to-start-developing-kubesphere)
|
||||
- [DevOps](#devops)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
KubeSphere only has few external dependencies you need to setup before being
|
||||
able to build and run the code.
|
||||
|
||||
### Setting up Go
|
||||
|
||||
KubeSphere written in the [Go](http://golang.org) programming language.
|
||||
To build, you'll need a Go (version 1.9+) development environment.
|
||||
If you haven't set up a Go development environment, please follow
|
||||
[these instructions](https://golang.org/doc/install)
|
||||
to install the Go tools.
|
||||
|
||||
Set up your GOPATH and add a path entry for Go binaries to your PATH. Typically
|
||||
added to your ~/.profile:
|
||||
|
||||
```shell
|
||||
$ export GOPATH=~/go
|
||||
$ export PATH=$PATH:$GOPATH/bin
|
||||
```
|
||||
|
||||
## To start developing KubeSphere
|
||||
|
||||
There are two options to get KubeSphere source code and build the project:
|
||||
|
||||
**You have a working Go environment.**
|
||||
|
||||
```shell
|
||||
$ go get -d kubesphere.io/kubesphere
|
||||
$ cd $GOPATH/src/kubesphere.io/kubesphere
|
||||
$ make all
|
||||
```
|
||||
|
||||
**You have a working Docker environment.**
|
||||
|
||||
```shell
|
||||
$ git clone https://github.com/kubesphere/kubesphere
|
||||
$ cd kubesphere
|
||||
$ make
|
||||
```
|
||||
316
docs/pull-requests.md
Normal file
316
docs/pull-requests.md
Normal file
@@ -0,0 +1,316 @@
|
||||
# Pull Request Process
|
||||
|
||||
This doc explains the process and best practices for submitting a PR to the [KubeSphere project](https://github.com/kubeSphere/kubeSphere). It should serve as a reference for all contributors, and be useful especially to new and infrequent submitters.
|
||||
|
||||
- [Before You Submit a PR](#before-you-submit-a-pr)
|
||||
* [Run Local Verifications](#run-local-verifications)
|
||||
- [The PR Submit Process](#the-pr-submit-process)
|
||||
* [Write Release Notes if Needed](#write-release-notes-if-needed)
|
||||
* [The Testing and Merge Workflow](#the-testing-and-merge-workflow)
|
||||
* [Marking Unfinished Pull Requests](#marking-unfinished-pull-requests)
|
||||
* [Comment Commands Reference](#comment-commands-reference)
|
||||
* [Automation](#automation)
|
||||
* [How the e2e Tests Work](#how-the-e2e-tests-work)
|
||||
- [Why was my PR closed?](#why-was-my-pr-closed)
|
||||
- [Why is my PR not getting reviewed?](#why-is-my-pr-not-getting-reviewed)
|
||||
- [Best Practices for Faster Reviews](#best-practices-for-faster-reviews)
|
||||
* [0. Familiarize yourself with project conventions](#0-familiarize-yourself-with-project-conventions)
|
||||
* [1. Is the feature wanted? Make a Design Doc or Sketch PR](#1-is-the-feature-wanted-make-a-design-doc-or-sketch-pr)
|
||||
* [2. Smaller Is Better: Small Commits, Small PRs](#2-smaller-is-better-small-commits-small-prs)
|
||||
* [3. Open a Different PR for Fixes and Generic Features](#3-open-a-different-pr-for-fixes-and-generic-features)
|
||||
* [4. Comments Matter](#4-comments-matter)
|
||||
* [5. Test](#5-test)
|
||||
* [6. Squashing and Commit Titles](#6-squashing-and-commit-titles)
|
||||
* [7. KISS, YAGNI, MVP, etc.](#7-kiss-yagni-mvp-etc)
|
||||
* [8. It's OK to Push Back](#8-its-ok-to-push-back)
|
||||
* [9. Common Sense and Courtesy](#9-common-sense-and-courtesy)
|
||||
|
||||
|
||||
# Before You Submit a PR
|
||||
|
||||
This guide is for contributors who already have a PR to submit. If you're looking for information on setting up your developer environment and creating code to contribute to KubeSphere, see the [development guide](development.md).
|
||||
|
||||
**Make sure your PR adheres to our best practices. These include following project conventions, making small PRs, and commenting thoroughly. Please read the more detailed section on [Best Practices for Faster Reviews](#best-practices-for-faster-reviews) at the end of this doc.**
|
||||
|
||||
## Run Local Verifications
|
||||
|
||||
You can run these local verifications before you submit your PR to predict the
|
||||
pass or fail of continuous integration.
|
||||
|
||||
# The PR Submit Process
|
||||
|
||||
Merging a PR requires the following steps to be completed before the PR will be merged automatically. For details about each step, see the [The Testing and Merge Workflow](#the-testing-and-merge-workflow) section below.
|
||||
|
||||
- Make the PR
|
||||
- Release notes - do one of the following:
|
||||
- Add notes in the release notes block, or
|
||||
- Update the release note label
|
||||
- Pass all tests
|
||||
- Get a `/lgtm` from a reviewer
|
||||
- Get approval from an owner
|
||||
|
||||
If your PR meets all of the steps above, it will enter the submit queue to be merged. When it is next in line to be merged, the tests will run a second time. If all tests pass, the PR will be merged automatically.
|
||||
|
||||
## Write Release Notes if Needed
|
||||
|
||||
Release notes are required for any PR with user-visible changes, such as bug-fixes, feature additions, and output format changes.
|
||||
|
||||
If you don't add release notes in the PR template, the `do-not-merge/release-note-label-needed` label is added to your PR automatically after you create it. There are a few ways to update it.
|
||||
|
||||
To add a release-note section to the PR description:
|
||||
|
||||
For PRs with a release note:
|
||||
|
||||
```release-note
|
||||
Your release note here
|
||||
```
|
||||
|
||||
For PRs that require additional action from users switching to the new release, include the string "action required" (case insensitive) in the release note:
|
||||
|
||||
```release-note
|
||||
action required: your release note here
|
||||
```
|
||||
|
||||
For PRs that don't need to be mentioned at release time, just write "NONE" (case insensitive):
|
||||
|
||||
```release-note
|
||||
NONE
|
||||
```
|
||||
|
||||
The `/release-note-none` comment command can still be used as an alternative to writing "NONE" in the release-note block if it is left empty.
|
||||
|
||||
To see how to format your release notes, view the [PR template](https://github.com/) for a brief example. PR titles and body comments can be modified at any time prior to the release to make them friendly for release notes.
|
||||
// PR template TODO
|
||||
|
||||
Release notes apply to PRs on the master branch. For cherry-pick PRs, see the [cherry-pick instructions](cherry-picks.md). The only exception to these rules is when a PR is not a cherry-pick and is targeted directly to the non-master branch. In this case, a `release-note-*` label is required for that non-master PR.
|
||||
|
||||
// cherry-pick TODO
|
||||
|
||||
Now that your release notes are in shape, let's look at how the PR gets tested and merged.
|
||||
|
||||
## The Testing and Merge Workflow
|
||||
|
||||
The KubeSphere merge workflow uses comments to run tests and labels for merging PRs.
|
||||
NOTE: For pull requests that are in progress but not ready for review,
|
||||
prefix the PR title with `WIP` or `[WIP]` and track any remaining TODOs
|
||||
in a checklist in the pull request description.
|
||||
|
||||
Here's the process the PR goes through on its way from submission to merging:
|
||||
|
||||
1. Make the pull request
|
||||
1. `@o8x-merge-robot` assigns reviewers //TODO
|
||||
|
||||
If you're **not** a member of the KubeSphere organization:
|
||||
|
||||
1. Reviewer/KubeSphere Member checks that the PR is safe to test. If so, they comment `/ok-to-test`
|
||||
1. Reviewer suggests edits
|
||||
1. Push edits to your PR branch
|
||||
1. Repeat the prior two steps as needed
|
||||
1. (Optional) Some reviewers prefer that you squash commits at this step
|
||||
1. Owner is assigned and will add the `/approve` label to the PR
|
||||
|
||||
If you are a member, or a member comments `/ok-to-test`, the PR will be considered to be trusted. Then the pre-submit tests will run:
|
||||
|
||||
1. Automatic tests run. See the current list of tests on the
|
||||
1. If tests fail, resolve issues by pushing edits to your PR branch
|
||||
1. If the failure is a flake, anyone on trusted PRs can comment `/retest` to rerun failed tests
|
||||
|
||||
Once the tests pass, all failures are commented as flakes, or the reviewer adds the labels `lgtm` and `approved`, the PR enters the final merge queue. The merge queue is needed to make sure no incompatible changes have been introduced by other PRs since the tests were last run on your PR.
|
||||
|
||||
Either the [on call contributor](on-call-rotations.md) will manage the merge queue manually. //TODO
|
||||
|
||||
1. The PR enters the merge queue ([http://submit-queue.KubeSphere.io]())
|
||||
1. The merge queue triggers a test re-run with the comment `/test all [submit-queue is verifying that this PR is safe to merge]`
|
||||
1. Author has signed the CLA (`cncf-cla: yes` label added to PR)
|
||||
1. No changes made since last `lgtm` label applied
|
||||
1. If tests fail, resolve issues by pushing edits to your PR branch
|
||||
1. If the failure is a flake, anyone can comment `/retest` if the PR is trusted
|
||||
1. If tests pass, the merge queue automatically merges the PR
|
||||
|
||||
That's the last step. Your PR is now merged.
|
||||
|
||||
## Marking Unfinished Pull Requests
|
||||
|
||||
If you want to solicit reviews before the implementation of your pull request is complete, you should hold your pull request to ensure that the merge queue does not pick it up and attempt to merge it. There are two methods to achieve this:
|
||||
|
||||
1. You may add the `/hold` or `/hold cancel` comment commands
|
||||
2. You may add or remove a `WIP` or `[WIP]` prefix to your pull request title
|
||||
|
||||
The GitHub robots will add and remove the `do-not-merge/hold` label as you use the comment commands and the `do-not-merge/work-in-progress` label as you edit your title. While either label is present, your pull request will not be considered for merging.
|
||||
|
||||
|
||||
## Comment Commands Reference//TODO
|
||||
|
||||
[The commands doc]() contains a reference for all comment commands. //TODO
|
||||
|
||||
## Automation//TODO
|
||||
|
||||
The KubeSphere developer community uses a variety of automation to manage pull requests. This automation is described in detail [in the automation doc](automation.md). //TODO
|
||||
|
||||
## How the Tests Work//TODO
|
||||
|
||||
The tests will post the status results to the PR. If an e2e test fails,
|
||||
`@o8x-ci-robot` will comment on the PR with the test history and the
|
||||
comment-command to re-run that test. e.g.
|
||||
|
||||
> The following tests failed, say /retest to rerun them all.
|
||||
|
||||
# Why was my PR closed?
|
||||
|
||||
Pull requests older than 90 days will be closed. Exceptions can be made for PRs that have active review comments, or that are awaiting other dependent PRs. Closed pull requests are easy to recreate, and little work is lost by closing a pull request that subsequently needs to be reopened. We want to limit the total number of PRs in flight to:
|
||||
* Maintain a clean project
|
||||
* Remove old PRs that would be difficult to rebase as the underlying code has changed over time
|
||||
* Encourage code velocity
|
||||
|
||||
# Why is my PR not getting reviewed?
|
||||
|
||||
A few factors affect how long your PR might wait for review.
|
||||
|
||||
If it's the last few weeks of a milestone, we need to reduce churn and stabilize.
|
||||
|
||||
Or, it could be related to best practices. One common issue is that the PR is too big to review. Let's say you've touched 39 files and have 8657 insertions. When your would-be reviewers pull up the diffs, they run away - this PR is going to take 4 hours to review and they don't have 4 hours right now. They'll get to it later, just as soon as they have more free time (ha!).
|
||||
|
||||
There is a detailed rundown of best practices, including how to avoid too-lengthy PRs, in the next section.
|
||||
|
||||
But, if you've already followed the best practices and you still aren't getting any PR love, here are some
|
||||
things you can do to move the process along:
|
||||
|
||||
* Make sure that your PR has an assigned reviewer (assignee in GitHub). If not, reply to the PR comment stream asking for a reviewer to be assigned.
|
||||
|
||||
* Ping the assignee (@username) on the PR comment stream, and ask for an estimate of when they can get to the review.
|
||||
|
||||
* Ping the assignee on [Slack](http://KubeSphere.slack.com). Remember that a person's GitHub username might not be the same as their Slack username.
|
||||
|
||||
* Ping the assignee by email (many of us have publicly available email addresses).
|
||||
|
||||
* If you're a member of the organization ping the [team](https://github.com/orgs/KubeSphere/teams) (via @team-name) that works in the area you're submitting code.
|
||||
|
||||
* If you have fixed all the issues from a review, and you haven't heard back, you should ping the assignee on the comment stream with a "please take another look" (`PTAL`) or similar comment indicating that you are ready for another review.
|
||||
|
||||
Read on to learn more about how to get faster reviews by following best practices.
|
||||
|
||||
# Best Practices for Faster Reviews
|
||||
|
||||
Most of this section is not specific to KubeSphere, but it's good to keep these best practices in mind when you're making a PR.
|
||||
|
||||
You've just had a brilliant idea on how to make KubeSphere better. Let's call that idea Feature-X. Feature-X is not even that complicated. You have a pretty good idea of how to implement it. You jump in and implement it, fixing a bunch of stuff along the way. You send your PR - this is awesome! And it sits. And sits. A week goes by and nobody reviews it. Finally, someone offers a few comments, which you fix up and wait for more review. And you wait. Another week or two go by. This is horrible.
|
||||
|
||||
Let's talk about best practices so your PR gets reviewed quickly.
|
||||
|
||||
## 0. Familiarize yourself with project conventions
|
||||
|
||||
* [Development guide](code-of-conduct.md)
|
||||
|
||||
## 1. Is the feature wanted? Make a Design Doc or Sketch PR
|
||||
|
||||
Are you sure Feature-X is something the KubeSphere team wants or will accept? Is it implemented to fit with other changes in flight? Are you willing to bet a few days or weeks of work on it?
|
||||
|
||||
It's better to get confirmation beforehand. There are two ways to do this:
|
||||
|
||||
- Make a proposal doc (in docs/proposals; for example [the QoS proposal]()
|
||||
- Coordinate your effort with [SIG Docs]() ahead of time. //TODO
|
||||
- Make a sketch PR (e.g., just the API or Go interface). Write or code up just enough to express the idea and the design and why you made those choices
|
||||
|
||||
Or, do all of the above.
|
||||
|
||||
Be clear about what type of feedback you are asking for when you submit a proposal doc or sketch PR.
|
||||
|
||||
Now, if we ask you to change the design, you won't have to re-write it all.
|
||||
|
||||
## 2. Smaller Is Better: Small Commits, Small PRs
|
||||
|
||||
Small commits and small PRs get reviewed faster and are more likely to be correct than big ones.
|
||||
|
||||
Attention is a scarce resource. If your PR takes 60 minutes to review, the reviewer's eye for detail is not as keen in the last 30 minutes as it was in the first. It might not get reviewed at all if it requires a large continuous block of time from the reviewer.
|
||||
|
||||
**Breaking up commits**
|
||||
|
||||
Break up your PR into multiple commits, at logical break points.
|
||||
|
||||
Making a series of discrete commits is a powerful way to express the evolution of an idea or the
|
||||
different ideas that make up a single feature. Strive to group logically distinct ideas into separate commits.
|
||||
|
||||
For example, if you found that Feature-X needed some prefactoring to fit in, make a commit that JUST does that prefactoring. Then make a new commit for Feature-X.
|
||||
|
||||
Strike a balance with the number of commits. A PR with 25 commits is still very cumbersome to review, so use
|
||||
judgment.
|
||||
|
||||
**Breaking up PRs**
|
||||
|
||||
Or, going back to our prefactoring example, you could also fork a new branch, do the prefactoring there and send a PR for that. If you can extract whole ideas from your PR and send those as PRs of their own, you can avoid the painful problem of continually rebasing.
|
||||
|
||||
KubeSphere is a fast-moving codebase - lock in your changes ASAP with your small PR, and make merges be someone else's problem.
|
||||
|
||||
Multiple small PRs are often better than multiple commits. Don't worry about flooding us with PRs. We'd rather have 100 small, obvious PRs than 10 unreviewable monoliths.
|
||||
|
||||
We want every PR to be useful on its own, so use your best judgment on what should be a PR vs. a commit.
|
||||
|
||||
As a rule of thumb, if your PR is directly related to Feature-X and nothing else, it should probably be part of the Feature-X PR. If you can explain why you are doing seemingly no-op work ("it makes the Feature-X change easier, I promise") we'll probably be OK with it. If you can imagine someone finding value independently of Feature-X, try it as a PR. (Do not link pull requests by `#` in a commit description, because GitHub creates lots of spam. Instead, reference other PRs via the PR your commit is in.)
|
||||
|
||||
## 3. Open a Different PR for Fixes and Generic Features
|
||||
|
||||
**Put changes that are unrelated to your feature into a different PR.**
|
||||
|
||||
Often, as you are implementing Feature-X, you will find bad comments, poorly named functions, bad structure, weak type-safety, etc.
|
||||
|
||||
You absolutely should fix those things (or at least file issues, please) - but not in the same PR as your feature. Otherwise, your diff will have way too many changes, and your reviewer won't see the forest for the trees.
|
||||
|
||||
**Look for opportunities to pull out generic features.**
|
||||
|
||||
For example, if you find yourself touching a lot of modules, think about the dependencies you are introducing between packages. Can some of what you're doing be made more generic and moved up and out of the Feature-X package? Do you need to use a function or type from an otherwise unrelated package? If so, promote! We have places for hosting more generic code.
|
||||
|
||||
Likewise, if Feature-X is similar in form to Feature-W which was checked in last month, and you're duplicating some tricky stuff from Feature-W, consider prefactoring the core logic out and using it in both Feature-W and
|
||||
Feature-X. (Do that in its own commit or PR, please.)
|
||||
|
||||
## 4. Comments Matter
|
||||
|
||||
In your code, if someone might not understand why you did something (or you won't remember why later), comment it. Many code-review comments are about this exact issue.
|
||||
|
||||
If you think there's something pretty obvious that we could follow up on, add a TODO.
|
||||
|
||||
Read up on [GoDoc](https://blog.golang.org/godoc-documenting-go-code) - follow those general rules for comments.
|
||||
|
||||
## 5. Test
|
||||
|
||||
Nothing is more frustrating than starting a review, only to find that the tests are inadequate or absent. Very few PRs can touch code and NOT touch tests.
|
||||
|
||||
If you don't know how to test Feature-X, please ask! We'll be happy to help you design things for easy testing or to suggest appropriate test cases.
|
||||
|
||||
## 6. Squashing and Commit Titles
|
||||
|
||||
Your reviewer has finally sent you feedback on Feature-X.
|
||||
|
||||
Make the fixups, and don't squash yet. Put them in a new commit, and re-push. That way your reviewer can look at the new commit on its own, which is much faster than starting over.
|
||||
|
||||
We might still ask you to clean up your commits at the very end for the sake of a more readable history, but don't do this until asked: typically at the point where the PR would otherwise be tagged `LGTM`.
|
||||
|
||||
Each commit should have a good title line (<70 characters) and include an additional description paragraph describing in more detail the change intended.
|
||||
|
||||
**General squashing guidelines:**
|
||||
|
||||
* Sausage => squash
|
||||
|
||||
Do squash when there are several commits to fix bugs in the original commit(s), address reviewer feedback, etc. Really we only want to see the end state and commit message for the whole PR.
|
||||
|
||||
* Layers => don't squash
|
||||
|
||||
Don't squash when there are independent changes layered to achieve a single goal. For instance, writing a code munger could be one commit, applying it could be another, and adding a precommit check could be a third. One could argue they should be separate PRs, but there's really no way to test/review the munger without seeing it applied, and there needs to be a precommit check to ensure the munged output doesn't immediately get out of date.
|
||||
|
||||
A commit, as much as possible, should be a single logical change.
|
||||
|
||||
## 7. KISS, YAGNI, MVP, etc.
|
||||
|
||||
Sometimes we need to remind each other of core tenets of software design - Keep It Simple, You Aren't Gonna Need It, Minimum Viable Product, and so on. Adding a feature "because we might need it later" is antithetical to software that ships. Add the things you need NOW and (ideally) leave room for things you might need later - but don't implement them now.
|
||||
|
||||
## 8. It's OK to Push Back
|
||||
|
||||
Sometimes reviewers make mistakes. It's OK to push back on changes your reviewer requested. If you have a good reason for doing something a certain way, you are absolutely allowed to debate the merits of a requested change. Both the reviewer and reviewee should strive to discuss these issues in a polite and respectful manner.
|
||||
|
||||
You might be overruled, but you might also prevail. We're pretty reasonable people. Mostly.
|
||||
|
||||
Another phenomenon of open-source projects (where anyone can comment on any issue) is the dog-pile - your PR gets so many comments from so many people it becomes hard to follow. In this situation, you can ask the primary reviewer (assignee) whether they want you to fork a new PR to clear out all the comments. You don't HAVE to fix every issue raised by every person who feels like commenting, but you should answer reasonable comments with an explanation.
|
||||
|
||||
## 9. Common Sense and Courtesy
|
||||
|
||||
No document can take the place of common sense and good taste. Use your best judgment, while you put
|
||||
a bit of thought into how your work can be made easier to review. If you do these things your PRs will get merged with less friction.
|
||||
37
docs/welcome-to-KubeSphere-new-developer-guide.md
Normal file
37
docs/welcome-to-KubeSphere-new-developer-guide.md
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
Welcome to KubeSphere! (New Developer Guide)
|
||||
============================================
|
||||
|
||||
_This document assumes that you know what KubeSphere does.
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This
|
||||
document will help you understand the organization of the KubeSphere project and
|
||||
direct you to the best places to get started. By the end of this doc, you'll be
|
||||
able to pick up issues, write code to fix them, and get your work reviewed and
|
||||
merged.
|
||||
|
||||
If you have questions about the development process, feel free to jump into our
|
||||
[Slack workspace](http://KubeSphere.slack.com/). If you join the
|
||||
Slack workspace it is recommended to set your Slack display name to your GitHub
|
||||
account handle.
|
||||
|
||||
|
||||
|
||||
Downloading, Building, and Testing KubeSphere
|
||||
---------------------------------------------
|
||||
|
||||
This guide is non-technical, so it does not cover the technical details of
|
||||
working KubeSphere. We have plenty of documentation available under
|
||||
[docs.kubesphere.io](https://docs.kubesphere.io).
|
||||
|
||||
Pull-Request Process
|
||||
--------------------
|
||||
|
||||
The pull-request process is documented in [pull-requests.md](pull-requests.md).
|
||||
As described in that document, you must sign the CLA before
|
||||
KubeSphere can accept your contribution.
|
||||
|
||||
Thanks for reading!
|
||||
15
hack/boilerplate.go.txt
Normal file
15
hack/boilerplate.go.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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.
|
||||
*/
|
||||
6
hack/docker_push.sh
Executable file
6
hack/docker_push.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Push image to dockerhub, need to support multiple push
|
||||
|
||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
docker push kubespheredev/ks-apiserver:latest
|
||||
45
hack/gobuild.sh
Executable file
45
hack/gobuild.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2017 KubeSphere 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.
|
||||
#
|
||||
# This script builds and link stamps the output
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
VERBOSE=${VERBOSE:-"0"}
|
||||
V=""
|
||||
if [[ "${VERBOSE}" == "1" ]];then
|
||||
V="-x"
|
||||
set -x
|
||||
fi
|
||||
|
||||
ROOTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
OUTPUT_DIR=${ROOTDIR}/bin
|
||||
BUILDPATH=${ROOTDIR}/${1:?"path to build"}
|
||||
OUT=${OUTPUT_DIR}/${1:?"output path"}
|
||||
|
||||
set -e
|
||||
|
||||
BUILD_GOOS=${GOOS:-linux}
|
||||
BUILD_GOARCH=${GOARCH:-amd64}
|
||||
GOBINARY=${GOBINARY:-go}
|
||||
|
||||
# forgoing -i (incremental build) because it will be deprecated by tool chain.
|
||||
time GOOS=${BUILD_GOOS} GOARCH=${BUILD_GOARCH} ${GOBINARY} build \
|
||||
-o ${OUT} \
|
||||
${BUILDPATH}
|
||||
24
install/ingress-controller/ingress-controller-svc.yaml
Normal file
24
install/ingress-controller/ingress-controller-svc.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kubesphere-router-gateway
|
||||
labels:
|
||||
app: kubesphere
|
||||
component: ks-router
|
||||
tier: backend
|
||||
spec:
|
||||
selector:
|
||||
app: kubesphere
|
||||
component: ks-router
|
||||
tier: backend
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
- name: https
|
||||
protocol: TCP
|
||||
port: 443
|
||||
targetPort: 443
|
||||
|
||||
69
install/ingress-controller/ingress-controller.yaml
Normal file
69
install/ingress-controller/ingress-controller.yaml
Normal file
@@ -0,0 +1,69 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ks-router
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kubesphere
|
||||
component: ks-router
|
||||
tier: backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kubesphere
|
||||
component: ks-router
|
||||
tier: backend
|
||||
annotations:
|
||||
prometheus.io/port: '10254'
|
||||
prometheus.io/scrape: 'true'
|
||||
spec:
|
||||
serviceAccountName: kubesphere-router-serviceaccount
|
||||
containers:
|
||||
- name: nginx-ingress-controller
|
||||
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.2
|
||||
args:
|
||||
- /nginx-ingress-controller
|
||||
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
|
||||
- --configmap=$(POD_NAMESPACE)/nginx-configuration
|
||||
- --annotations-prefix=nginx.ingress.kubernetes.io
|
||||
- --force-namespace-isolation
|
||||
- --update-status
|
||||
- --update-status-on-shutdown
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
- name: https
|
||||
containerPort: 443
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10254
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 1
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10254
|
||||
scheme: HTTP
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 1
|
||||
securityContext:
|
||||
runAsNonRoot: false
|
||||
|
||||
4
install/scripts/docker_push
Normal file
4
install/scripts/docker_push
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
docker push kubespheredev/ks-apiserver:latest
|
||||
BIN
install/swagger-ui/favicon-16x16.png
Normal file
BIN
install/swagger-ui/favicon-16x16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 445 B |
BIN
install/swagger-ui/favicon-32x32.png
Normal file
BIN
install/swagger-ui/favicon-32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
60
install/swagger-ui/index.html
Normal file
60
install/swagger-ui/index.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "/swagger-ui/api.json",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
67
install/swagger-ui/oauth2-redirect.html
Normal file
67
install/swagger-ui/oauth2-redirect.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<body onload="run()">
|
||||
</body>
|
||||
</html>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1);
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&")
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value)
|
||||
}
|
||||
) : {}
|
||||
|
||||
isValid = qp.state === sentState
|
||||
|
||||
if ((
|
||||
oauth2.auth.schema.get("flow") === "accessCode"||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode"
|
||||
) && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||
} else {
|
||||
let oauthErrorMsg
|
||||
if (qp.error) {
|
||||
oauthErrorMsg = "["+qp.error+"]: " +
|
||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
104
install/swagger-ui/swagger-ui-bundle.js
Normal file
104
install/swagger-ui/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
install/swagger-ui/swagger-ui-bundle.js.map
Normal file
1
install/swagger-ui/swagger-ui-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
14
install/swagger-ui/swagger-ui-standalone-preset.js
Normal file
14
install/swagger-ui/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
1
install/swagger-ui/swagger-ui-standalone-preset.js.map
Normal file
1
install/swagger-ui/swagger-ui-standalone-preset.js.map
Normal file
File diff suppressed because one or more lines are too long
3
install/swagger-ui/swagger-ui.css
Normal file
3
install/swagger-ui/swagger-ui.css
Normal file
File diff suppressed because one or more lines are too long
1
install/swagger-ui/swagger-ui.css.map
Normal file
1
install/swagger-ui/swagger-ui.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""}
|
||||
9
install/swagger-ui/swagger-ui.js
Normal file
9
install/swagger-ui/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
1
install/swagger-ui/swagger-ui.js.map
Normal file
1
install/swagger-ui/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
30
pkg/apis/apis.go
Normal file
30
pkg/apis/apis.go
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 apis contains KubeSphere API groups.
|
||||
package apis
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// AddToSchemes may be used to add all resources defined in the project to a Scheme
|
||||
var AddToSchemes runtime.SchemeBuilder
|
||||
|
||||
// AddToScheme adds all Resources to the Scheme
|
||||
func AddToScheme(s *runtime.Scheme) error {
|
||||
return AddToSchemes.AddToScheme(s)
|
||||
}
|
||||
18
pkg/apis/metrics/group.go
Normal file
18
pkg/apis/metrics/group.go
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 metrics
|
||||
33
pkg/apis/metrics/install/install.go
Normal file
33
pkg/apis/metrics/install/install.go
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 install
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
metrcisv1alpha2 "kubesphere.io/kubesphere/pkg/apis/metrics/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Install(runtime.Container)
|
||||
}
|
||||
|
||||
func Install(container *restful.Container) {
|
||||
urlruntime.Must(metrcisv1alpha2.AddToContainer(container))
|
||||
}
|
||||
45
pkg/apis/metrics/v1alpha2/register.go
Normal file
45
pkg/apis/metrics/v1alpha2/register.go
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 v1alpha2
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/metrics"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
)
|
||||
|
||||
const GroupName = "metrics.kubesphere.io"
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
var (
|
||||
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
|
||||
AddToContainer = WebServiceBuilder.AddToContainer
|
||||
)
|
||||
|
||||
func addWebService(c *restful.Container) error {
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
|
||||
webservice.Route(webservice.GET("/storageclasses/{storageclass}").To(metrics.GetScMetrics))
|
||||
webservice.Route(webservice.GET("/metrics/storageclass").To(metrics.GetScMetricsList))
|
||||
|
||||
c.Add(webservice)
|
||||
|
||||
return nil
|
||||
}
|
||||
18
pkg/apis/operations/group.go
Normal file
18
pkg/apis/operations/group.go
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 operations
|
||||
33
pkg/apis/operations/install/install.go
Normal file
33
pkg/apis/operations/install/install.go
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 install
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
operationsv1alpha2 "kubesphere.io/kubesphere/pkg/apis/operations/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Install(runtime.Container)
|
||||
}
|
||||
|
||||
func Install(container *restful.Container) {
|
||||
urlruntime.Must(operationsv1alpha2.AddToContainer(container))
|
||||
}
|
||||
58
pkg/apis/operations/v1alpha2/register.go
Normal file
58
pkg/apis/operations/v1alpha2/register.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 v1alpha2
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/operations"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
)
|
||||
|
||||
const GroupName = "operations.kubesphere.io"
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
var (
|
||||
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
|
||||
AddToContainer = WebServiceBuilder.AddToContainer
|
||||
)
|
||||
|
||||
func addWebService(c *restful.Container) error {
|
||||
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
|
||||
webservice.Route(webservice.POST("/nodes/{node}/drainage").To(operations.DrainNode))
|
||||
|
||||
webservice.Route(webservice.POST("/namespaces/{namespace}/jobs/{job}").
|
||||
To(operations.RerunJob).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{"jobs"}).
|
||||
Doc("Handle job operation").
|
||||
Param(webservice.PathParameter("job", "job name").
|
||||
DataType("string")).
|
||||
Param(webservice.PathParameter("namespace", "job's namespace").
|
||||
DataType("string")).
|
||||
Param(webservice.QueryParameter("a", "action").
|
||||
DataType("string")).
|
||||
Writes(""))
|
||||
|
||||
c.Add(webservice)
|
||||
|
||||
return nil
|
||||
}
|
||||
18
pkg/apis/resources/group.go
Normal file
18
pkg/apis/resources/group.go
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 metrics
|
||||
33
pkg/apis/resources/install/install.go
Normal file
33
pkg/apis/resources/install/install.go
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 install
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
resourcev1alpha2 "kubesphere.io/kubesphere/pkg/apis/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Install(runtime.Container)
|
||||
}
|
||||
|
||||
func Install(c *restful.Container) {
|
||||
urlruntime.Must(resourcev1alpha2.AddToContainer(c))
|
||||
}
|
||||
57
pkg/apis/resources/v1alpha2/register.go
Normal file
57
pkg/apis/resources/v1alpha2/register.go
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 v1alpha2
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/resources"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
)
|
||||
|
||||
const GroupName = "resources.kubesphere.io"
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
var (
|
||||
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
|
||||
AddToContainer = WebServiceBuilder.AddToContainer
|
||||
)
|
||||
|
||||
func addWebService(c *restful.Container) error {
|
||||
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}").To(resources.NamespaceResourceHandler))
|
||||
|
||||
webservice.Route(webservice.GET("/{resources}").To(resources.ClusterResourceHandler))
|
||||
|
||||
webservice.Route(webservice.GET("/storageclasses/{storageclass}/persistentvolumeclaims").To(resources.GetPvcListBySc))
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/persistentvolumeclaims/{pvc}/pods").To(resources.GetPodListByPvc))
|
||||
|
||||
tags := []string{"users"}
|
||||
webservice.Route(webservice.GET("/users/{username}/kubectl").Doc("get user's kubectl pod").Param(webservice.PathParameter("username",
|
||||
"username").DataType("string")).Metadata(restfulspec.KeyOpenAPITags, tags).To(resources.GetKubectl))
|
||||
webservice.Route(webservice.GET("/users/{username}/kubeconfig").Doc("get users' kubeconfig").Param(webservice.PathParameter("username",
|
||||
"username").DataType("string")).Metadata(restfulspec.KeyOpenAPITags, tags).To(resources.GetKubeconfig))
|
||||
|
||||
c.Add(webservice)
|
||||
|
||||
return nil
|
||||
}
|
||||
66
pkg/apiserver/components/components.go
Normal file
66
pkg/apiserver/components/components.go
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 components
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/components"
|
||||
)
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
ws.Route(ws.GET("/components").To(getComponents))
|
||||
ws.Route(ws.GET("/components/{component}").To(getComponentStatus))
|
||||
ws.Route(ws.GET("/health").To(getSystemHealthStatus))
|
||||
}
|
||||
|
||||
func getSystemHealthStatus(request *restful.Request, response *restful.Response) {
|
||||
result, err := components.GetAllComponentsStatus()
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// get a specific component status
|
||||
func getComponentStatus(request *restful.Request, response *restful.Response) {
|
||||
component := request.PathParameter("component")
|
||||
|
||||
result, err := components.GetComponentStatus(component)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// get all componentsHandler
|
||||
func getComponents(request *restful.Request, response *restful.Response) {
|
||||
|
||||
result, err := components.GetAllComponentsStatus()
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
52
pkg/apiserver/hpa/hpa.go
Normal file
52
pkg/apiserver/hpa/hpa.go
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 hpa
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/api/autoscaling/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/hpa"
|
||||
)
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/horizontalpodautoscalers/{horizontalpodautoscaler}").
|
||||
To(getHpa).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{"hpa"}).
|
||||
Doc("get horizontalpodautoscalers").
|
||||
Param(ws.PathParameter("namespace", "horizontalpodautoscalers's namespace").
|
||||
DataType("string")).
|
||||
Param(ws.PathParameter("horizontalpodautoscaler", "horizontalpodautoscaler's name")).
|
||||
Writes(v1.HorizontalPodAutoscaler{}))
|
||||
}
|
||||
|
||||
func getHpa(req *restful.Request, resp *restful.Response) {
|
||||
name := req.PathParameter("horizontalpodautoscaler")
|
||||
namespace := req.PathParameter("namespace")
|
||||
|
||||
result, err := hpa.GetHPA(namespace, name)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
76
pkg/apiserver/metrics/metrics.go
Normal file
76
pkg/apiserver/metrics/metrics.go
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 metrics
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/storage"
|
||||
)
|
||||
|
||||
type scMetricsItem struct {
|
||||
Name string `json:"name"`
|
||||
Metrics *storage.ScMetrics `json:"metrics"`
|
||||
}
|
||||
|
||||
// Get StorageClass item
|
||||
// Extended API URL: "GET /api/v1alpha1/storage/storageclasses/{storageclass}/metrics"
|
||||
func GetScMetrics(request *restful.Request, response *restful.Response) {
|
||||
scName := request.PathParameter("storageclass")
|
||||
|
||||
metrics, err := storage.GetScMetrics(scName)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
result := scMetricsItem{
|
||||
Name: scName, Metrics: metrics,
|
||||
}
|
||||
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// Get StorageClass item list
|
||||
// Extended API URL: "GET /api/v1alpha1/storage/storageclasses/metrics"
|
||||
func GetScMetricsList(request *restful.Request, response *restful.Response) {
|
||||
scList, err := storage.GetScList()
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
// Set return value
|
||||
items := make([]scMetricsItem, 0)
|
||||
|
||||
for _, v := range scList {
|
||||
metrics, err := storage.GetScMetrics(v.GetName())
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
item := scMetricsItem{
|
||||
Name: v.GetName(), Metrics: metrics,
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
response.WriteAsJson(items)
|
||||
}
|
||||
51
pkg/apiserver/operations/job.go
Normal file
51
pkg/apiserver/operations/job.go
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 operations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/workloads"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func RerunJob(req *restful.Request, resp *restful.Response) {
|
||||
var err error
|
||||
|
||||
job := req.PathParameter("job")
|
||||
namespace := req.PathParameter("namespace")
|
||||
action := req.QueryParameter("a")
|
||||
|
||||
switch action {
|
||||
case "rerun":
|
||||
err = workloads.JobReRun(namespace, job)
|
||||
default:
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, fmt.Sprintf("invalid operation %s", action)))
|
||||
return
|
||||
}
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(errors.None)
|
||||
}
|
||||
39
pkg/apiserver/operations/node.go
Normal file
39
pkg/apiserver/operations/node.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 operations
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/nodes"
|
||||
)
|
||||
|
||||
func DrainNode(request *restful.Request, response *restful.Response) {
|
||||
|
||||
nodeName := request.PathParameter("node")
|
||||
|
||||
err := nodes.DrainNode(nodeName)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(errors.None)
|
||||
}
|
||||
69
pkg/apiserver/quotas/quotas.go
Normal file
69
pkg/apiserver/quotas/quotas.go
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 quotas
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/models/quotas"
|
||||
)
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
|
||||
tags := []string{"quotas"}
|
||||
|
||||
ws.Route(ws.GET("/quotas").
|
||||
To(getClusterQuotas).
|
||||
Doc("get whole cluster's resource usage").
|
||||
Writes(quotas.ResourceQuota{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/quotas").
|
||||
Doc("get specified namespace's resource quota and usage").
|
||||
Param(ws.PathParameter("namespace", "namespace's name").
|
||||
DataType("string")).
|
||||
Writes(quotas.ResourceQuota{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
To(getNamespaceQuotas))
|
||||
|
||||
}
|
||||
|
||||
func getNamespaceQuotas(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
quota, err := quotas.GetNamespaceQuotas(namespace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(quota)
|
||||
}
|
||||
|
||||
func getClusterQuotas(req *restful.Request, resp *restful.Response) {
|
||||
quota, err := quotas.GetClusterQuotas()
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(quota)
|
||||
}
|
||||
74
pkg/apiserver/registries/registries.go
Normal file
74
pkg/apiserver/registries/registries.go
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 registries
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/registries"
|
||||
)
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
|
||||
ws.Route(ws.POST("registries/verify").To(registryVerify))
|
||||
|
||||
}
|
||||
|
||||
func registryVerify(request *restful.Request, response *restful.Response) {
|
||||
|
||||
authInfo := registries.AuthInfo{}
|
||||
|
||||
err := request.ReadEntity(&authInfo)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
err = registries.RegistryVerify(authInfo)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(errors.None)
|
||||
}
|
||||
|
||||
//func (c *registriesHandler) handlerImageSearch(request *restful.Request, response *restful.Response) {
|
||||
//
|
||||
// registry := request.PathParameter("name")
|
||||
// searchWord := request.PathParameter("searchWord")
|
||||
// namespace := request.PathParameter("namespace")
|
||||
//
|
||||
// res := c.registries.ImageSearch(namespace, registry, searchWord)
|
||||
//
|
||||
// response.WriteAsJson(res)
|
||||
//
|
||||
//}
|
||||
//
|
||||
//func (c *registriesHandler) handlerGetImageTags(request *restful.Request, response *restful.Response) {
|
||||
//
|
||||
// registry := request.PathParameter("name")
|
||||
// image := request.QueryParameter("image")
|
||||
// namespace := request.PathParameter("namespace")
|
||||
//
|
||||
// res := c.registries.GetImageTags(namespace, registry, image)
|
||||
//
|
||||
// response.WriteAsJson(res)
|
||||
//}
|
||||
42
pkg/apiserver/resources/cluster_resources.go
Normal file
42
pkg/apiserver/resources/cluster_resources.go
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 resources
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources"
|
||||
"kubesphere.io/kubesphere/pkg/params"
|
||||
)
|
||||
|
||||
func ClusterResourceHandler(req *restful.Request, resp *restful.Response) {
|
||||
resourceName := req.PathParameter("resources")
|
||||
conditions := req.QueryParameter(params.Conditions)
|
||||
orderBy := req.QueryParameter(params.OrderBy)
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.Paging))
|
||||
reverse := params.ParseReserve(req.QueryParameter(params.Reserve))
|
||||
|
||||
result, err := resources.ListClusterResource(resourceName, conditions, orderBy, reverse, limit, offset)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
43
pkg/apiserver/resources/namespace_resources.go
Normal file
43
pkg/apiserver/resources/namespace_resources.go
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 resources
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources"
|
||||
"kubesphere.io/kubesphere/pkg/params"
|
||||
)
|
||||
|
||||
func NamespaceResourceHandler(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
resourceName := req.PathParameter("resources")
|
||||
conditions := req.QueryParameter(params.Conditions)
|
||||
orderBy := req.QueryParameter(params.OrderBy)
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.Paging))
|
||||
reverse := params.ParseReserve(req.QueryParameter(params.Reserve))
|
||||
|
||||
result, err := resources.ListNamespaceResource(namespace, resourceName, conditions, orderBy, reverse, limit, offset)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
68
pkg/apiserver/resources/storage.go
Normal file
68
pkg/apiserver/resources/storage.go
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 resources
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/storage"
|
||||
)
|
||||
|
||||
type pvcList struct {
|
||||
Name string `json:"name"`
|
||||
Items []*v1.PersistentVolumeClaim `json:"items"`
|
||||
}
|
||||
|
||||
type podListByPvc struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
Pods []*v1.Pod `json:"pods"`
|
||||
}
|
||||
|
||||
// List all pods of a specific PVC
|
||||
// Extended API URL: "GET /api/v1alpha2/namespaces/{namespace}/persistentvolumeclaims/{name}/pods"
|
||||
func GetPodListByPvc(request *restful.Request, response *restful.Response) {
|
||||
|
||||
pvcName := request.PathParameter("pvc")
|
||||
nsName := request.PathParameter("namespace")
|
||||
pods, err := storage.GetPodListByPvc(pvcName, nsName)
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
result := podListByPvc{Name: pvcName, Namespace: nsName, Pods: pods}
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// List all PersistentVolumeClaims of a specific StorageClass
|
||||
// Extended API URL: "GET /api/v1alpha2/storageclasses/{storageclass}/persistentvolumeclaims"
|
||||
func GetPvcListBySc(request *restful.Request, response *restful.Response) {
|
||||
scName := request.PathParameter("storageclass")
|
||||
claims, err := storage.GetPvcListBySc(scName)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
result := pvcList{
|
||||
Name: scName, Items: claims,
|
||||
}
|
||||
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
52
pkg/apiserver/resources/user.go
Normal file
52
pkg/apiserver/resources/user.go
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 resources
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/kubeconfig"
|
||||
"kubesphere.io/kubesphere/pkg/models/kubectl"
|
||||
)
|
||||
|
||||
func GetKubectl(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
user := req.PathParameter("username")
|
||||
|
||||
kubectlPod, err := kubectl.GetKubectlPod(user)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(kubectlPod)
|
||||
}
|
||||
|
||||
func GetKubeconfig(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
user := req.PathParameter("username")
|
||||
|
||||
kubectlConfig, err := kubeconfig.GetKubeConfig(user)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(kubectlConfig)
|
||||
}
|
||||
116
pkg/apiserver/revisions/revisions.go
Normal file
116
pkg/apiserver/revisions/revisions.go
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 revisions
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/api/apps/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/revisions"
|
||||
)
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/daemonsets/{daemonset}/revisions/{revision}").
|
||||
To(getDaemonSetRevision).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{"daemonsets", "revision"}).
|
||||
Doc("Handle daemonset operation").
|
||||
Param(ws.PathParameter("daemonset", "daemonset's name").
|
||||
DataType("string")).
|
||||
Param(ws.PathParameter("namespace", "daemonset's namespace").
|
||||
DataType("string")).
|
||||
Param(ws.PathParameter("revision", "daemonset's revision")).
|
||||
Writes(v1.DaemonSet{}))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/deployments/{deployment}/revisions/{revision}").
|
||||
To(getDeployRevision).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{"deployments", "revision"}).
|
||||
Doc("Handle deployment operation").
|
||||
Param(ws.PathParameter("deployment", "deployment's name").
|
||||
DataType("string")).
|
||||
Param(ws.PathParameter("namespace",
|
||||
"deployment's namespace").
|
||||
DataType("string")).
|
||||
Param(ws.PathParameter("deployment", "deployment's name")).
|
||||
Writes(v1.ReplicaSet{}))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/statefulsets/{statefulset}/revisions/{revision}").
|
||||
To(getStatefulSetRevision).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{"statefulsets", "revisions"}).
|
||||
Doc("Handle statefulset operation").
|
||||
Param(ws.PathParameter("statefulset", "statefulset's name").
|
||||
DataType("string")).
|
||||
Param(ws.PathParameter("namespace", "statefulset's namespace").
|
||||
DataType("string")).
|
||||
Param(ws.PathParameter("revision", "statefulset's revision")).
|
||||
Writes(v1.StatefulSet{}))
|
||||
}
|
||||
|
||||
func getDaemonSetRevision(req *restful.Request, resp *restful.Response) {
|
||||
daemonset := req.PathParameter("daemonset")
|
||||
namespace := req.PathParameter("namespace")
|
||||
revision, err := strconv.Atoi(req.PathParameter("revision"))
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
result, err := revisions.GetDaemonSetRevision(namespace, daemonset, revision)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
|
||||
func getDeployRevision(req *restful.Request, resp *restful.Response) {
|
||||
deploy := req.PathParameter("deployment")
|
||||
namespace := req.PathParameter("namespace")
|
||||
revision := req.PathParameter("revision")
|
||||
|
||||
result, err := revisions.GetDeployRevision(namespace, deploy, revision)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
|
||||
func getStatefulSetRevision(req *restful.Request, resp *restful.Response) {
|
||||
statefulset := req.PathParameter("statefulset")
|
||||
namespace := req.PathParameter("namespace")
|
||||
revision, err := strconv.Atoi(req.PathParameter("revision"))
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
result, err := revisions.GetStatefulSetRevision(namespace, statefulset, revision)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
187
pkg/apiserver/routers/routers.go
Normal file
187
pkg/apiserver/routers/routers.go
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 routers
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/models/routers"
|
||||
)
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
ws.Route(ws.GET("/routers").To(getAllRouters).
|
||||
Doc("Get all routers"))
|
||||
|
||||
ws.Route(ws.GET("/users/{username}/routers").To(getAllRoutersOfUser).
|
||||
Doc("Get routers for user"))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/router").To(getRouter).
|
||||
Doc("Get router of a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").
|
||||
DataType("string")))
|
||||
|
||||
ws.Route(ws.DELETE("/namespaces/{namespace}/router").To(deleteRouter).
|
||||
Doc("Get router of a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").
|
||||
DataType("string")))
|
||||
|
||||
ws.Route(ws.POST("/namespaces/{namespace}/router").To(createRouter).
|
||||
Doc("Create a router for a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").
|
||||
DataType("string")))
|
||||
|
||||
ws.Route(ws.PUT("/namespaces/{namespace}/router").To(updateRouter).
|
||||
Doc("Update a router for a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").
|
||||
DataType("string")))
|
||||
}
|
||||
|
||||
type Router struct {
|
||||
RouterType string `json:"type"`
|
||||
Annotations map[string]string `json:"annotations"`
|
||||
}
|
||||
|
||||
// Get all namespace ingress controller services
|
||||
func getAllRouters(request *restful.Request, response *restful.Response) {
|
||||
|
||||
routers, err := routers.GetAllRouters()
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(routers)
|
||||
}
|
||||
|
||||
// Get all namespace ingress controller services for user
|
||||
func getAllRoutersOfUser(request *restful.Request, response *restful.Response) {
|
||||
|
||||
username := request.PathParameter("username")
|
||||
|
||||
routers, err := routers.GetAllRoutersOfUser(username)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(routers)
|
||||
}
|
||||
|
||||
// Get ingress controller service for specified namespace
|
||||
func getRouter(request *restful.Request, response *restful.Response) {
|
||||
|
||||
namespace := request.PathParameter("namespace")
|
||||
router, err := routers.GetRouter(namespace)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(router)
|
||||
}
|
||||
|
||||
// Create ingress controller and related services
|
||||
func createRouter(request *restful.Request, response *restful.Response) {
|
||||
|
||||
namespace := request.PathParameter("namespace")
|
||||
|
||||
newRouter := Router{}
|
||||
err := request.ReadEntity(&newRouter)
|
||||
|
||||
if err != nil {
|
||||
response.WriteAsJson(err)
|
||||
return
|
||||
}
|
||||
|
||||
var router *v1.Service
|
||||
|
||||
serviceType, annotationMap, err := ParseParameter(newRouter)
|
||||
|
||||
if err != nil {
|
||||
glog.Error("Wrong annotations, missing key or value")
|
||||
response.WriteHeaderAndEntity(http.StatusBadRequest,
|
||||
errors.New(errors.InvalidArgument, "Wrong annotations, missing key or value"))
|
||||
return
|
||||
}
|
||||
|
||||
router, err = routers.CreateRouter(namespace, serviceType, annotationMap)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(router)
|
||||
}
|
||||
|
||||
// Delete ingress controller and services
|
||||
func deleteRouter(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
|
||||
router, err := routers.DeleteRouter(namespace)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(router)
|
||||
}
|
||||
|
||||
func updateRouter(request *restful.Request, response *restful.Response) {
|
||||
|
||||
namespace := request.PathParameter("namespace")
|
||||
|
||||
newRouter := Router{}
|
||||
err := request.ReadEntity(&newRouter)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
serviceType, annotationMap, err := ParseParameter(newRouter)
|
||||
|
||||
router, err := routers.UpdateRouter(namespace, serviceType, annotationMap)
|
||||
|
||||
if errors.HandlerError(err, response) {
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteAsJson(router)
|
||||
}
|
||||
|
||||
func ParseParameter(router Router) (routerType v1.ServiceType, annotationMap map[string]string, err error) {
|
||||
|
||||
routerType = v1.ServiceTypeNodePort
|
||||
|
||||
if strings.Compare(strings.ToLower(router.RouterType), "loadbalancer") == 0 {
|
||||
return v1.ServiceTypeLoadBalancer, router.Annotations, nil
|
||||
} else {
|
||||
return v1.ServiceTypeNodePort, make(map[string]string, 0), nil
|
||||
}
|
||||
|
||||
}
|
||||
64
pkg/apiserver/runtime/runtime.go
Normal file
64
pkg/apiserver/runtime/runtime.go
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 runtime
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
ApiRootPath = "/apis"
|
||||
)
|
||||
|
||||
// container holds all webservice of apiserver
|
||||
var Container = restful.NewContainer()
|
||||
|
||||
type ContainerBuilder []func(c *restful.Container) error
|
||||
|
||||
//
|
||||
func NewWebService(gv schema.GroupVersion) *restful.WebService {
|
||||
webservice := restful.WebService{}
|
||||
|
||||
webservice.Path(ApiRootPath + "/" + gv.String())
|
||||
|
||||
return &webservice
|
||||
}
|
||||
|
||||
func (cb *ContainerBuilder) AddToContainer(c *restful.Container) error {
|
||||
for _, f := range *cb {
|
||||
if err := f(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cb *ContainerBuilder) Register(funcs ...func(*restful.Container) error) {
|
||||
for _, f := range funcs {
|
||||
*cb = append(*cb, f)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
func NewContainerBuilder(funcs ...func(*restful.Container) error) ContainerBuilder {
|
||||
var cb ContainerBuilder
|
||||
cb.Register(funcs...)
|
||||
|
||||
return cb
|
||||
}
|
||||
59
pkg/apiserver/workloadstatuses/workloadstatuses.go
Normal file
59
pkg/apiserver/workloadstatuses/workloadstatuses.go
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 workloadstatuses
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/status"
|
||||
)
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
tags := []string{"workloadStatus"}
|
||||
|
||||
ws.Route(ws.GET("/workloadstatuses").
|
||||
Doc("get abnormal workloads' count of whole cluster").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
To(getClusterResourceStatus))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/workloadstatuses").
|
||||
Doc("get abnormal workloads' count of specified namespace").
|
||||
Param(ws.PathParameter("namespace", "the name of namespace").
|
||||
DataType("string")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
To(getNamespacesResourceStatus))
|
||||
|
||||
}
|
||||
|
||||
func getClusterResourceStatus(req *restful.Request, resp *restful.Response) {
|
||||
res, err := status.GetClusterResourceStatus()
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
resp.WriteAsJson(res)
|
||||
}
|
||||
|
||||
func getNamespacesResourceStatus(req *restful.Request, resp *restful.Response) {
|
||||
res, err := status.GetNamespacesResourceStatus(req.PathParameter("namespace"))
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
resp.WriteAsJson(res)
|
||||
}
|
||||
506
pkg/apiserver/workspaces/workspaces.go
Normal file
506
pkg/apiserver/workspaces/workspaces.go
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 workspaces
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/metrics"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"strconv"
|
||||
|
||||
"regexp"
|
||||
|
||||
"sort"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||
)
|
||||
|
||||
const UserNameHeader = "X-Token-Username"
|
||||
|
||||
func V1Alpha2(ws *restful.WebService) {
|
||||
ws.Route(ws.GET("/workspaces").To(UserWorkspaceListHandler))
|
||||
ws.Route(ws.POST("/workspaces").To(WorkspaceCreateHandler))
|
||||
ws.Route(ws.DELETE("/workspaces/{name}").To(DeleteWorkspaceHandler))
|
||||
ws.Route(ws.GET("/workspaces/{name}").To(WorkspaceDetailHandler))
|
||||
ws.Route(ws.PUT("/workspaces/{name}").To(WorkspaceEditHandler))
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/namespaces").To(UserNamespaceListHandler))
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/members/{username}/namespaces").To(UserNamespaceListHandler))
|
||||
ws.Route(ws.POST("/workspaces/{name}/namespaces").To(NamespaceCreateHandler))
|
||||
ws.Route(ws.DELETE("/workspaces/{name}/namespaces/{namespace}").To(NamespaceDeleteHandler))
|
||||
ws.Route(ws.GET("/workspaces/{name}/namespaces/{namespace}").To(NamespaceCheckHandler))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}").To(NamespaceCheckHandler))
|
||||
ws.Route(ws.GET("/workspaces/{name}/devops").To(DevOpsProjectHandler))
|
||||
ws.Route(ws.GET("/workspaces/{name}/members/{username}/devops").To(DevOpsProjectHandler))
|
||||
ws.Route(ws.POST("/workspaces/{name}/devops").To(DevOpsProjectCreateHandler))
|
||||
ws.Route(ws.DELETE("/workspaces/{name}/devops/{id}").To(DevOpsProjectDeleteHandler))
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{name}/members").To(MembersHandler))
|
||||
ws.Route(ws.GET("/workspaces/{name}/members/{member}").To(MemberHandler))
|
||||
ws.Route(ws.GET("/workspaces/{name}/roles").To(RolesHandler))
|
||||
// TODO /workspaces/{name}/roles/{role}
|
||||
ws.Route(ws.POST("/workspaces/{name}/members").To(MembersInviteHandler))
|
||||
ws.Route(ws.DELETE("/workspaces/{name}/members").To(MembersRemoveHandler))
|
||||
}
|
||||
|
||||
func RolesHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
name := req.PathParameter("name")
|
||||
|
||||
workspace, err := workspaces.Detail(name)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
roles, err := workspaces.Roles(workspace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(roles)
|
||||
}
|
||||
|
||||
func MembersHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("name")
|
||||
keyword := req.QueryParameter("keyword")
|
||||
|
||||
users, err := workspaces.GetWorkspaceMembers(workspace, keyword)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(users)
|
||||
}
|
||||
|
||||
func MemberHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.PathParameter("member")
|
||||
|
||||
user, err := iam.GetUser(username)
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
namespaces, err := workspaces.Namespaces(workspace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
user.WorkspaceRole = user.WorkspaceRoles[workspace]
|
||||
|
||||
roles := make(map[string]string)
|
||||
|
||||
for _, namespace := range namespaces {
|
||||
if role := user.Roles[namespace.Name]; role != "" {
|
||||
roles[namespace.Name] = role
|
||||
}
|
||||
}
|
||||
|
||||
user.Roles = roles
|
||||
user.Rules = nil
|
||||
user.WorkspaceRules = nil
|
||||
user.WorkspaceRoles = nil
|
||||
user.ClusterRules = nil
|
||||
resp.WriteAsJson(user)
|
||||
}
|
||||
|
||||
func MembersInviteHandler(req *restful.Request, resp *restful.Response) {
|
||||
var users []workspaces.UserInvite
|
||||
workspace := req.PathParameter("name")
|
||||
err := req.ReadEntity(&users)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
err = workspaces.Invite(workspace, users)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(errors.None)
|
||||
}
|
||||
|
||||
func MembersRemoveHandler(req *restful.Request, resp *restful.Response) {
|
||||
query := req.QueryParameter("name")
|
||||
workspace := req.PathParameter("name")
|
||||
|
||||
names := strings.Split(query, ",")
|
||||
|
||||
err := workspaces.RemoveMembers(workspace, names)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(errors.None)
|
||||
}
|
||||
|
||||
func NamespaceCheckHandler(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
|
||||
exist, err := workspaces.NamespaceExistCheck(namespace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(map[string]bool{"exist": exist})
|
||||
}
|
||||
|
||||
func NamespaceDeleteHandler(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
workspace := req.PathParameter("name")
|
||||
|
||||
err := workspaces.DeleteNamespace(workspace, namespace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(errors.None)
|
||||
}
|
||||
|
||||
func DevOpsProjectDeleteHandler(req *restful.Request, resp *restful.Response) {
|
||||
devops := req.PathParameter("id")
|
||||
workspace := req.PathParameter("name")
|
||||
force := req.QueryParameter("force")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
err := workspaces.UnBindDevopsProject(workspace, devops)
|
||||
|
||||
if err != nil && force != "true" {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.New(errors.Internal, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
err = workspaces.DeleteDevopsProject(username, devops)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(errors.None)
|
||||
}
|
||||
|
||||
func DevOpsProjectCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
var devops workspaces.DevopsProject
|
||||
|
||||
err := req.ReadEntity(&devops)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
project, err := workspaces.CreateDevopsProject(username, workspace, devops)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(project)
|
||||
|
||||
}
|
||||
|
||||
func NamespaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
namespace := &v1.Namespace{}
|
||||
|
||||
err := req.ReadEntity(namespace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if namespace.Annotations == nil {
|
||||
namespace.Annotations = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
namespace.Annotations["creator"] = username
|
||||
namespace.Annotations["workspace"] = workspace
|
||||
|
||||
if namespace.Labels == nil {
|
||||
namespace.Labels = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
namespace.Labels["kubesphere.io/workspace"] = workspace
|
||||
|
||||
namespace, err = workspaces.CreateNamespace(namespace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(namespace)
|
||||
}
|
||||
|
||||
func DevOpsProjectHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.PathParameter("username")
|
||||
keyword := req.QueryParameter("keyword")
|
||||
|
||||
if username == "" {
|
||||
username = req.HeaderParameter(UserNameHeader)
|
||||
}
|
||||
|
||||
limit := 65535
|
||||
offset := 0
|
||||
orderBy := "createTime"
|
||||
reverse := true
|
||||
|
||||
if groups := regexp.MustCompile(`^limit=(\d+),page=(\d+)$`).FindStringSubmatch(req.QueryParameter("paging")); len(groups) == 3 {
|
||||
limit, _ = strconv.Atoi(groups[1])
|
||||
page, _ := strconv.Atoi(groups[2])
|
||||
offset = (page - 1) * limit
|
||||
}
|
||||
|
||||
if groups := regexp.MustCompile(`^(createTime|name)$`).FindStringSubmatch(req.QueryParameter("order")); len(groups) == 2 {
|
||||
orderBy = groups[1]
|
||||
reverse = false
|
||||
}
|
||||
|
||||
if q := req.QueryParameter("reverse"); q != "" {
|
||||
b, err := strconv.ParseBool(q)
|
||||
if err == nil {
|
||||
reverse = b
|
||||
}
|
||||
}
|
||||
|
||||
total, devOpsProjects, err := workspaces.ListDevopsProjectsByUser(username, workspace, keyword, orderBy, reverse, limit, offset)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
result := models.PageableResponse{}
|
||||
result.TotalCount = total
|
||||
result.Items = make([]interface{}, 0)
|
||||
for _, n := range devOpsProjects {
|
||||
result.Items = append(result.Items, n)
|
||||
}
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
|
||||
func WorkspaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
var workspace workspaces.Workspace
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
err := req.ReadEntity(&workspace)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
if workspace.Name == "" || strings.Contains(workspace.Name, ":") {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, "invalid workspace name"))
|
||||
return
|
||||
}
|
||||
|
||||
workspace.Path = workspace.Name
|
||||
workspace.Members = nil
|
||||
|
||||
if workspace.Admin != "" {
|
||||
workspace.Creator = workspace.Admin
|
||||
} else {
|
||||
workspace.Creator = username
|
||||
}
|
||||
|
||||
created, err := workspaces.Create(&workspace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(created)
|
||||
|
||||
}
|
||||
|
||||
func DeleteWorkspaceHandler(req *restful.Request, resp *restful.Response) {
|
||||
name := req.PathParameter("name")
|
||||
|
||||
if name == "" || strings.Contains(name, ":") {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, "invalid workspace name"))
|
||||
return
|
||||
}
|
||||
|
||||
workspace, err := workspaces.Detail(name)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
err = workspaces.Delete(workspace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(errors.None)
|
||||
}
|
||||
func WorkspaceEditHandler(req *restful.Request, resp *restful.Response) {
|
||||
var workspace workspaces.Workspace
|
||||
name := req.PathParameter("name")
|
||||
err := req.ReadEntity(&workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if name != workspace.Name {
|
||||
resp.WriteError(http.StatusBadRequest, fmt.Errorf("the name of workspace (%s) does not match the name on the URL (%s)", workspace.Name, name))
|
||||
return
|
||||
}
|
||||
|
||||
if workspace.Name == "" || strings.Contains(workspace.Name, ":") {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.New(errors.InvalidArgument, "invalid workspace name"))
|
||||
return
|
||||
}
|
||||
|
||||
workspace.Path = workspace.Name
|
||||
|
||||
workspace.Members = nil
|
||||
|
||||
edited, err := workspaces.Edit(&workspace)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(edited)
|
||||
}
|
||||
func WorkspaceDetailHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
name := req.PathParameter("name")
|
||||
|
||||
workspace, err := workspaces.Detail(name)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteAsJson(workspace)
|
||||
}
|
||||
|
||||
// List all workspaces for the current user
|
||||
func UserWorkspaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
keyword := req.QueryParameter("keyword")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
ws, err := workspaces.ListWorkspaceByUser(username, keyword)
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
sort.Slice(ws, func(i, j int) bool {
|
||||
t1, err := ws[i].GetCreateTime()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
t2, err := ws[j].GetCreateTime()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return t1.After(t2)
|
||||
})
|
||||
|
||||
resp.WriteAsJson(ws)
|
||||
}
|
||||
|
||||
func UserNamespaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
withMetrics, err := strconv.ParseBool(req.QueryParameter("metrics"))
|
||||
|
||||
if err != nil {
|
||||
withMetrics = false
|
||||
}
|
||||
|
||||
username := req.PathParameter("username")
|
||||
keyword := req.QueryParameter("keyword")
|
||||
if username == "" {
|
||||
username = req.HeaderParameter(UserNameHeader)
|
||||
}
|
||||
limit := 65535
|
||||
offset := 0
|
||||
orderBy := "createTime"
|
||||
reverse := true
|
||||
|
||||
if groups := regexp.MustCompile(`^limit=(\d+),page=(\d+)$`).FindStringSubmatch(req.QueryParameter("paging")); len(groups) == 3 {
|
||||
limit, _ = strconv.Atoi(groups[1])
|
||||
page, _ := strconv.Atoi(groups[2])
|
||||
if page < 0 {
|
||||
page = 1
|
||||
}
|
||||
offset = (page - 1) * limit
|
||||
}
|
||||
|
||||
if groups := regexp.MustCompile(`^(createTime|name)$`).FindStringSubmatch(req.QueryParameter("order")); len(groups) == 2 {
|
||||
orderBy = groups[1]
|
||||
reverse = false
|
||||
}
|
||||
|
||||
if q := req.QueryParameter("reverse"); q != "" {
|
||||
b, err := strconv.ParseBool(q)
|
||||
if err == nil {
|
||||
reverse = b
|
||||
}
|
||||
}
|
||||
|
||||
workspaceName := req.PathParameter("workspace")
|
||||
|
||||
total, namespaces, err := workspaces.ListNamespaceByUser(workspaceName, username, keyword, orderBy, reverse, limit, offset)
|
||||
|
||||
if withMetrics {
|
||||
namespaces = metrics.GetNamespacesWithMetrics(namespaces)
|
||||
}
|
||||
|
||||
if errors.HandlerError(err, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
result := models.PageableResponse{}
|
||||
result.TotalCount = total
|
||||
result.Items = make([]interface{}, 0)
|
||||
for _, n := range namespaces {
|
||||
result.Items = append(result.Items, n)
|
||||
}
|
||||
|
||||
resp.WriteAsJson(result)
|
||||
}
|
||||
51
pkg/client/dbclient.go
Normal file
51
pkg/client/dbclient.go
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere 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 client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/golang/glog"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
var dbClient *gorm.DB
|
||||
|
||||
func NewDBClient() *gorm.DB {
|
||||
conn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", "", "", "", "")
|
||||
|
||||
db, err := gorm.Open("mysql", conn)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func NewSharedDBClient() *gorm.DB {
|
||||
|
||||
if dbClient != nil {
|
||||
err := dbClient.DB().Ping()
|
||||
if err == nil {
|
||||
return dbClient
|
||||
} else {
|
||||
glog.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
return NewDBClient()
|
||||
}
|
||||
97
pkg/client/k8sclient.go
Normal file
97
pkg/client/k8sclient.go
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
var (
|
||||
KubeConfigFile string
|
||||
k8sClient *kubernetes.Clientset
|
||||
k8sClientOnce sync.Once
|
||||
KubeConfig *rest.Config
|
||||
)
|
||||
|
||||
func K8sClient() *kubernetes.Clientset {
|
||||
|
||||
k8sClientOnce.Do(func() {
|
||||
|
||||
config, err := getKubeConfig()
|
||||
|
||||
if err != nil {
|
||||
glog.Fatalf("cannot load kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
k8sClient, err = kubernetes.NewForConfig(config)
|
||||
|
||||
if err != nil {
|
||||
glog.Fatalf("cannot create k8s client: %v", err)
|
||||
}
|
||||
|
||||
KubeConfig = config
|
||||
})
|
||||
|
||||
return k8sClient
|
||||
}
|
||||
|
||||
func getKubeConfig() (kubeConfig *rest.Config, err error) {
|
||||
|
||||
if KubeConfigFile == "" {
|
||||
if env := os.Getenv("KUBECONFIG"); env != "" {
|
||||
KubeConfigFile = env
|
||||
} else {
|
||||
if home, err := homedir.Dir(); err == nil {
|
||||
KubeConfigFile = fmt.Sprintf("%s/.kube/config", home)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if KubeConfigFile != "" {
|
||||
|
||||
kubeConfig, err = clientcmd.BuildConfigFromFlags("", KubeConfigFile)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
kubeConfig, err = rest.InClusterConfig()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
kubeConfig.QPS = 1e6
|
||||
kubeConfig.Burst = 1e6
|
||||
|
||||
return kubeConfig, nil
|
||||
|
||||
}
|
||||
192
pkg/client/prometheusclient.go
Normal file
192
pkg/client/prometheusclient.go
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere 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 client
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"os"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultScheme = "http"
|
||||
DefaultPrometheusPort = "9090"
|
||||
PrometheusApiPath = "/api/v1/"
|
||||
DefaultQueryStep = "10m"
|
||||
DefaultQueryTimeout = "10s"
|
||||
RangeQueryType = "query_range?"
|
||||
DefaultQueryType = "query?"
|
||||
PrometheusAPIServerEnv = "PROMETHEUS_API_SERVER"
|
||||
)
|
||||
|
||||
var PrometheusAPIServer = "prometheus-k8s.kubesphere-monitoring-system.svc"
|
||||
var PrometheusEndpointUrl string
|
||||
|
||||
func init() {
|
||||
if env := os.Getenv(PrometheusAPIServerEnv); env != "" {
|
||||
PrometheusAPIServer = env
|
||||
}
|
||||
PrometheusEndpointUrl = DefaultScheme + "://" + PrometheusAPIServer + ":" + DefaultPrometheusPort + PrometheusApiPath
|
||||
}
|
||||
|
||||
type MonitoringRequestParams struct {
|
||||
Params url.Values
|
||||
QueryType string
|
||||
SortMetricName string
|
||||
SortType string
|
||||
PageNum string
|
||||
LimitNum string
|
||||
Tp string
|
||||
MetricsFilter string
|
||||
NodesFilter string
|
||||
WsFilter string
|
||||
NsFilter string
|
||||
PodsFilter string
|
||||
ContainersFilter string
|
||||
MetricsName string
|
||||
WorkloadName string
|
||||
WlFilter string
|
||||
NodeId string
|
||||
WsName string
|
||||
NsName string
|
||||
PodName string
|
||||
ContainerName string
|
||||
WorkloadKind string
|
||||
}
|
||||
|
||||
var client = &http.Client{}
|
||||
|
||||
func SendMonitoringRequest(queryType string, params string) string {
|
||||
epurl := PrometheusEndpointUrl + queryType + params
|
||||
response, err := client.Get(epurl)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
defer response.Body.Close()
|
||||
|
||||
contents, err := ioutil.ReadAll(response.Body)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
return string(contents)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func ParseMonitoringRequestParams(request *restful.Request) *MonitoringRequestParams {
|
||||
instantTime := strings.Trim(request.QueryParameter("time"), " ")
|
||||
start := strings.Trim(request.QueryParameter("start"), " ")
|
||||
end := strings.Trim(request.QueryParameter("end"), " ")
|
||||
step := strings.Trim(request.QueryParameter("step"), " ")
|
||||
timeout := strings.Trim(request.QueryParameter("timeout"), " ")
|
||||
|
||||
sortMetricName := strings.Trim(request.QueryParameter("sort_metric"), " ")
|
||||
sortType := strings.Trim(request.QueryParameter("sort_type"), " ")
|
||||
pageNum := strings.Trim(request.QueryParameter("page"), " ")
|
||||
limitNum := strings.Trim(request.QueryParameter("limit"), " ")
|
||||
tp := strings.Trim(request.QueryParameter("type"), " ")
|
||||
|
||||
metricsFilter := strings.Trim(request.QueryParameter("metrics_filter"), " ")
|
||||
nodesFilter := strings.Trim(request.QueryParameter("nodes_filter"), " ")
|
||||
wsFilter := strings.Trim(request.QueryParameter("workspaces_filter"), " ")
|
||||
nsFilter := strings.Trim(request.QueryParameter("namespaces_filter"), " ")
|
||||
wlFilter := strings.Trim(request.QueryParameter("workloads_filter"), " ")
|
||||
podsFilter := strings.Trim(request.QueryParameter("pods_filter"), " ")
|
||||
containersFilter := strings.Trim(request.QueryParameter("containers_filter"), " ")
|
||||
|
||||
metricsName := strings.Trim(request.QueryParameter("metrics_name"), " ")
|
||||
workloadName := strings.Trim(request.QueryParameter("workload_name"), " ")
|
||||
|
||||
nodeId := strings.Trim(request.PathParameter("node_id"), " ")
|
||||
wsName := strings.Trim(request.PathParameter("workspace_name"), " ")
|
||||
nsName := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
podName := strings.Trim(request.PathParameter("pod_name"), " ")
|
||||
containerName := strings.Trim(request.PathParameter("container_name"), " ")
|
||||
workloadKind := strings.Trim(request.PathParameter("workload_kind"), " ")
|
||||
|
||||
var requestParams = MonitoringRequestParams{
|
||||
SortMetricName: sortMetricName,
|
||||
SortType: sortType,
|
||||
PageNum: pageNum,
|
||||
LimitNum: limitNum,
|
||||
Tp: tp,
|
||||
MetricsFilter: metricsFilter,
|
||||
NodesFilter: nodesFilter,
|
||||
WsFilter: wsFilter,
|
||||
NsFilter: nsFilter,
|
||||
PodsFilter: podsFilter,
|
||||
ContainersFilter: containersFilter,
|
||||
MetricsName: metricsName,
|
||||
WorkloadName: workloadName,
|
||||
WlFilter: wlFilter,
|
||||
NodeId: nodeId,
|
||||
WsName: wsName,
|
||||
NsName: nsName,
|
||||
PodName: podName,
|
||||
ContainerName: containerName,
|
||||
WorkloadKind: workloadKind,
|
||||
}
|
||||
|
||||
if timeout == "" {
|
||||
timeout = DefaultQueryTimeout
|
||||
}
|
||||
if step == "" {
|
||||
step = DefaultQueryStep
|
||||
}
|
||||
// Whether query or query_range request
|
||||
u := url.Values{}
|
||||
|
||||
if start != "" && end != "" {
|
||||
u.Set("start", convertTimeGranularity(start))
|
||||
u.Set("end", convertTimeGranularity(end))
|
||||
u.Set("step", step)
|
||||
u.Set("timeout", timeout)
|
||||
requestParams.QueryType = RangeQueryType
|
||||
requestParams.Params = u
|
||||
return &requestParams
|
||||
}
|
||||
if instantTime != "" {
|
||||
u.Set("time", instantTime)
|
||||
u.Set("timeout", timeout)
|
||||
requestParams.QueryType = DefaultQueryType
|
||||
requestParams.Params = u
|
||||
return &requestParams
|
||||
} else {
|
||||
//u.Set("time", strconv.FormatInt(int64(time.Now().Unix()), 10))
|
||||
u.Set("timeout", timeout)
|
||||
requestParams.QueryType = DefaultQueryType
|
||||
requestParams.Params = u
|
||||
return &requestParams
|
||||
}
|
||||
}
|
||||
|
||||
func convertTimeGranularity(ts string) string {
|
||||
timeFloat, err := strconv.ParseFloat(ts, 64)
|
||||
if err != nil {
|
||||
glog.Errorf("convert second timestamp %s to minute timestamp failed", ts)
|
||||
return strconv.FormatInt(int64(time.Now().Unix()), 10)
|
||||
}
|
||||
timeInt := int64(timeFloat)
|
||||
// convert second timestamp to minute timestamp
|
||||
secondTime := time.Unix(timeInt, 0).Truncate(time.Minute).Unix()
|
||||
return strconv.FormatInt(secondTime, 10)
|
||||
}
|
||||
55
pkg/constants/constants.go
Normal file
55
pkg/constants/constants.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package constants
|
||||
|
||||
import "os"
|
||||
|
||||
const (
|
||||
APIVersion = "v1alpha1"
|
||||
|
||||
KubeSystemNamespace = "kube-system"
|
||||
OpenPitrixNamespace = "openpitrix-system"
|
||||
IstioNamespace = "istio-system"
|
||||
KubeSphereNamespace = "kubesphere-system"
|
||||
KubeSphereControlNamespace = "kubesphere-controls-system"
|
||||
IngressControllerNamespace = KubeSphereControlNamespace
|
||||
AdminUserName = "admin"
|
||||
DataHome = "/etc/kubesphere"
|
||||
IngressControllerFolder = DataHome + "/ingress-controller"
|
||||
IngressControllerPrefix = "kubesphere-router-"
|
||||
|
||||
WorkspaceLabelKey = "kubesphere.io/workspace"
|
||||
WorkspaceAdmin = "workspace-admin"
|
||||
ClusterAdmin = "cluster-admin"
|
||||
WorkspaceRegular = "workspace-regular"
|
||||
WorkspaceViewer = "workspace-viewer"
|
||||
DevopsOwner = "owner"
|
||||
DevopsReporter = "reporter"
|
||||
|
||||
DevopsAPIServerEnv = "DEVOPS_API_SERVER"
|
||||
AccountAPIServerEnv = "ACCOUNT_API_SERVER"
|
||||
DevopsProxyTokenEnv = "DEVOPS_PROXY_TOKEN"
|
||||
OpenPitrixProxyTokenEnv = "OPENPITRIX_PROXY_TOKEN"
|
||||
)
|
||||
|
||||
var (
|
||||
WorkSpaceRoles = []string{WorkspaceAdmin, WorkspaceRegular, WorkspaceViewer}
|
||||
DevopsAPIServer = "ks-devops-apiserver.kubesphere-system.svc"
|
||||
AccountAPIServer = "ks-account.kubesphere-system.svc"
|
||||
DevopsProxyToken = ""
|
||||
OpenPitrixProxyToken = ""
|
||||
SystemNamespaces = []string{KubeSystemNamespace, OpenPitrixNamespace, KubeSystemNamespace}
|
||||
)
|
||||
|
||||
func init() {
|
||||
if env := os.Getenv(DevopsAPIServerEnv); env != "" {
|
||||
DevopsAPIServer = env
|
||||
}
|
||||
if env := os.Getenv(AccountAPIServerEnv); env != "" {
|
||||
AccountAPIServer = env
|
||||
}
|
||||
if env := os.Getenv(DevopsProxyTokenEnv); env != "" {
|
||||
DevopsProxyToken = env
|
||||
}
|
||||
if env := os.Getenv(OpenPitrixProxyTokenEnv); env != "" {
|
||||
OpenPitrixProxyToken = env
|
||||
}
|
||||
}
|
||||
34
pkg/controller/controller.go
Normal file
34
pkg/controller/controller.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere 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 controller
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
)
|
||||
|
||||
// AddToManagerFuncs is a list of functions to add all Controllers to the Manager
|
||||
var AddToManagerFuncs []func(manager.Manager) error
|
||||
|
||||
// AddToManager adds all Controllers to the Manager
|
||||
func AddToManager(m manager.Manager) error {
|
||||
for _, f := range AddToManagerFuncs {
|
||||
if err := f(m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
29
pkg/controller/controllers.go
Normal file
29
pkg/controller/controllers.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/controller/namespace"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/informers"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
const defaultResync = 600 * time.Second
|
||||
|
||||
var once sync.Once
|
||||
|
||||
func Run(stopCh <-chan struct{}) {
|
||||
once.Do(func() {
|
||||
kubeclientset := client.K8sClient()
|
||||
informerFactory := informers.NewSharedInformerFactory(kubeclientset, defaultResync)
|
||||
namespaceController := namespace.NewNamespaceController(kubeclientset, informerFactory.Core().V1().Namespaces(), informerFactory.Rbac().V1().Roles())
|
||||
// data sync
|
||||
informerFactory.Start(stopCh)
|
||||
// start workers
|
||||
namespaceController.Start(stopCh)
|
||||
log.Println("all controller is running")
|
||||
})
|
||||
}
|
||||
10
pkg/controller/controllers_test.go
Normal file
10
pkg/controller/controllers_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// controller test
|
||||
func TestController(t *testing.T) {
|
||||
|
||||
}
|
||||
191
pkg/controller/namespace/namespaces.go
Normal file
191
pkg/controller/namespace/namespaces.go
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 namespace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/informers/rbac/v1"
|
||||
rbacinformers "k8s.io/client-go/informers/rbac/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
)
|
||||
|
||||
const threadiness = 2
|
||||
|
||||
var (
|
||||
defaultRoles = []rbac.Role{
|
||||
{ObjectMeta: metaV1.ObjectMeta{Name: "admin", Annotations: map[string]string{"creator": "system"}}, Rules: []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}},
|
||||
{ObjectMeta: metaV1.ObjectMeta{Name: "operator", Annotations: map[string]string{"creator": "system"}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}, {Verbs: []string{"*"}, APIGroups: []string{"", "apps", "extensions", "batch", "kubesphere.io", "account.kubesphere.io", "autoscaling"}, Resources: []string{"*"}}}},
|
||||
{ObjectMeta: metaV1.ObjectMeta{Name: "viewer", Annotations: map[string]string{"creator": "system"}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}},
|
||||
}
|
||||
)
|
||||
|
||||
type NamespaceController struct {
|
||||
clientset kubernetes.Interface
|
||||
namespaceInformer coreinformers.NamespaceInformer
|
||||
roleInformer v1.RoleInformer
|
||||
workqueue workqueue.RateLimitingInterface
|
||||
}
|
||||
|
||||
func NewNamespaceController(
|
||||
kubeclientset kubernetes.Interface,
|
||||
namespaceInformer coreinformers.NamespaceInformer,
|
||||
roleInformer rbacinformers.RoleInformer) *NamespaceController {
|
||||
|
||||
controller := &NamespaceController{
|
||||
clientset: kubeclientset,
|
||||
namespaceInformer: namespaceInformer,
|
||||
roleInformer: roleInformer,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespaces"),
|
||||
}
|
||||
|
||||
glog.Info("setting up event handlers")
|
||||
|
||||
namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: controller.handleObject,
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
newNamespace := new.(*corev1.Namespace)
|
||||
oldNamespace := old.(*corev1.Namespace)
|
||||
if newNamespace.ResourceVersion == oldNamespace.ResourceVersion {
|
||||
return
|
||||
}
|
||||
controller.handleObject(new)
|
||||
},
|
||||
DeleteFunc: controller.handleObject,
|
||||
})
|
||||
|
||||
roleInformer.Lister()
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
func (c *NamespaceController) Start(stopCh <-chan struct{}) {
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.workqueue.ShutDown()
|
||||
|
||||
// Start the informer factories to begin populating the informer caches
|
||||
glog.Info("starting namespace controller")
|
||||
|
||||
// Wait for the caches to be synced before starting workers
|
||||
glog.Info("waiting for informer caches to sync")
|
||||
if ok := cache.WaitForCacheSync(stopCh, c.namespaceInformer.Informer().HasSynced, c.roleInformer.Informer().HasSynced); !ok {
|
||||
glog.Fatalf("controller exit with error: failed to wait for caches to sync")
|
||||
}
|
||||
|
||||
glog.Info("starting workers")
|
||||
|
||||
for i := 0; i < threadiness; i++ {
|
||||
go wait.Until(c.runWorker, time.Second, stopCh)
|
||||
}
|
||||
|
||||
glog.Info("started workers")
|
||||
<-stopCh
|
||||
glog.Info("shutting down workers")
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *NamespaceController) runWorker() {
|
||||
for c.processNextWorkItem() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *NamespaceController) processNextWorkItem() bool {
|
||||
obj, shutdown := c.workqueue.Get()
|
||||
|
||||
if shutdown {
|
||||
return false
|
||||
}
|
||||
|
||||
err := func(obj interface{}) error {
|
||||
defer c.workqueue.Done(obj)
|
||||
var namespace string
|
||||
var ok bool
|
||||
|
||||
if namespace, ok = obj.(string); !ok {
|
||||
c.workqueue.Forget(obj)
|
||||
utilruntime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := c.syncHandler(namespace); err != nil {
|
||||
c.workqueue.AddRateLimited(namespace)
|
||||
return fmt.Errorf("error syncing '%s': %s, requeuing", namespace, err.Error())
|
||||
}
|
||||
|
||||
c.workqueue.Forget(obj)
|
||||
glog.Infof("successfully namespace synced '%s'", namespace)
|
||||
return nil
|
||||
}(obj)
|
||||
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *NamespaceController) syncHandler(name string) error {
|
||||
|
||||
_, err := c.namespaceInformer.Lister().Get(name)
|
||||
|
||||
// Handler delete event
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handler update or create event
|
||||
if err := c.checkRoles(name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *NamespaceController) handleObject(obj interface{}) {
|
||||
if namespace, ok := obj.(*corev1.Namespace); ok {
|
||||
c.workqueue.AddRateLimited(namespace.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *NamespaceController) checkRoles(namespace string) error {
|
||||
for _, role := range defaultRoles {
|
||||
_, err := c.roleInformer.Lister().Roles(namespace).Get(role.Name)
|
||||
if errors.IsNotFound(err) {
|
||||
r := role.DeepCopy()
|
||||
r.Namespace = namespace
|
||||
_, err := c.clientset.RbacV1().Roles(namespace).Create(r)
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
17
pkg/errors/code.go
Normal file
17
pkg/errors/code.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package errors
|
||||
|
||||
type Code int
|
||||
|
||||
const (
|
||||
OK Code = iota
|
||||
Canceled
|
||||
Unknown
|
||||
InvalidArgument
|
||||
Internal // 5
|
||||
Unavailable
|
||||
AlreadyExists
|
||||
NotFound
|
||||
NotImplement
|
||||
VerifyFailed
|
||||
Conflict
|
||||
)
|
||||
16
pkg/errors/code_string.go
Normal file
16
pkg/errors/code_string.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type=Code"; DO NOT EDIT.
|
||||
|
||||
package errors
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _Code_name = "OKCanceledUnknownInvalidArgumentInternalUnavailableAlreadyExistsWTFNotFoundNotImplementVerifyFailed"
|
||||
|
||||
var _Code_index = [...]uint8{0, 2, 10, 17, 32, 40, 51, 64, 67, 75, 87, 99}
|
||||
|
||||
func (i Code) String() string {
|
||||
if i < 0 || i >= Code(len(_Code_index)-1) {
|
||||
return "Code(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Code_name[_Code_index[i]:_Code_index[i+1]]
|
||||
}
|
||||
7
pkg/errors/code_test.go
Normal file
7
pkg/errors/code_test.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package errors
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCode_String(t *testing.T) {
|
||||
t.Log(Code(1).String())
|
||||
}
|
||||
114
pkg/errors/errors.go
Normal file
114
pkg/errors/errors.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
k8sError "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Code Code `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
var None = New(OK, "success")
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("error: %v,message: %v", e.Code.String(), e.Message)
|
||||
}
|
||||
func (e *Error) HttpStatusCode() int {
|
||||
switch e.Code {
|
||||
case OK:
|
||||
return http.StatusOK
|
||||
case InvalidArgument:
|
||||
return http.StatusBadRequest
|
||||
case AlreadyExists:
|
||||
return http.StatusConflict
|
||||
case Unavailable:
|
||||
return http.StatusServiceUnavailable
|
||||
case NotImplement:
|
||||
return http.StatusNotImplemented
|
||||
case VerifyFailed:
|
||||
return http.StatusBadRequest
|
||||
case Conflict:
|
||||
return http.StatusConflict
|
||||
case Internal:
|
||||
fallthrough
|
||||
case Unknown:
|
||||
fallthrough
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
|
||||
func New(code Code, message string) error {
|
||||
if message == "" {
|
||||
message = code.String()
|
||||
}
|
||||
return &Error{Code: code, Message: message}
|
||||
}
|
||||
|
||||
func HandlerError(err error, resp *restful.Response) bool {
|
||||
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
glog.Errorln(reflect.TypeOf(err), err)
|
||||
|
||||
resp.WriteHeaderAndEntity(wrapper(err))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func wrapper(err error) (int, interface{}) {
|
||||
switch err.(type) {
|
||||
case *Error:
|
||||
case *json.UnmarshalTypeError:
|
||||
err = New(InvalidArgument, err.Error())
|
||||
case *mysql.MySQLError:
|
||||
err = wrapperMysqlError(err.(*mysql.MySQLError))
|
||||
case *net.OpError:
|
||||
err = New(Internal, err.Error())
|
||||
default:
|
||||
if k8sError.IsNotFound(err) {
|
||||
err = New(NotFound, err.Error())
|
||||
} else {
|
||||
err = New(Unknown, err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
return err.(*Error).HttpStatusCode(), err
|
||||
}
|
||||
|
||||
func wrapperMysqlError(sqlError *mysql.MySQLError) error {
|
||||
switch sqlError.Number {
|
||||
case 1062:
|
||||
return New(AlreadyExists, sqlError.Message)
|
||||
default:
|
||||
return New(Unknown, sqlError.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func Wrap(data []byte) error {
|
||||
var j map[string]string
|
||||
err := json.Unmarshal(data, &j)
|
||||
if err != nil {
|
||||
return errors.New(string(data))
|
||||
} else if message := j["message"]; message != "" {
|
||||
return errors.New(message)
|
||||
} else if message := j["Error"]; message != "" {
|
||||
return errors.New(message)
|
||||
} else {
|
||||
return errors.New(string(data))
|
||||
}
|
||||
}
|
||||
41
pkg/filter/logging.go
Normal file
41
pkg/filter/logging.go
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 filter
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func Logging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
start := time.Now()
|
||||
chain.ProcessFilter(req, resp)
|
||||
glog.Infof("%s - \"%s %s %s\" %d %d %dms",
|
||||
strings.Split(req.Request.RemoteAddr, ":")[0],
|
||||
req.Request.Method,
|
||||
req.Request.RequestURI,
|
||||
req.Request.Proto,
|
||||
resp.StatusCode(),
|
||||
resp.ContentLength(),
|
||||
time.Since(start)/time.Millisecond,
|
||||
)
|
||||
}
|
||||
42
pkg/informers/informers.go
Normal file
42
pkg/informers/informers.go
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 informers
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/informers"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
const defaultResync = 600 * time.Second
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
informerFactory informers.SharedInformerFactory
|
||||
)
|
||||
|
||||
func SharedInformerFactory() informers.SharedInformerFactory {
|
||||
once.Do(func() {
|
||||
k8sClient := client.K8sClient()
|
||||
informerFactory = informers.NewSharedInformerFactory(k8sClient, defaultResync)
|
||||
})
|
||||
return informerFactory
|
||||
}
|
||||
204
pkg/models/components/components.go
Normal file
204
pkg/models/components/components.go
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 components
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
lister "k8s.io/client-go/listers/core/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
|
||||
"github.com/golang/glog"
|
||||
coreV1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
type Component struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
SelfLink string `json:"selfLink"`
|
||||
Label interface{} `json:"label"`
|
||||
StartedAt time.Time `json:"startedAt"`
|
||||
TotalBackends int `json:"totalBackends"`
|
||||
HealthyBackends int `json:"healthyBackends"`
|
||||
}
|
||||
|
||||
var (
|
||||
componentStatusLister lister.ComponentStatusLister
|
||||
serviceLister lister.ServiceLister
|
||||
podLister lister.PodLister
|
||||
nodeLister lister.NodeLister
|
||||
)
|
||||
|
||||
func init() {
|
||||
componentStatusLister = informers.SharedInformerFactory().Core().V1().ComponentStatuses().Lister()
|
||||
serviceLister = informers.SharedInformerFactory().Core().V1().Services().Lister()
|
||||
podLister = informers.SharedInformerFactory().Core().V1().Pods().Lister()
|
||||
nodeLister = informers.SharedInformerFactory().Core().V1().Nodes().Lister()
|
||||
}
|
||||
|
||||
func GetComponentStatus(name string) (interface{}, error) {
|
||||
|
||||
var service *coreV1.Service
|
||||
var err error
|
||||
for _, ns := range constants.SystemNamespaces {
|
||||
service, err = serviceLister.Services(ns).Get(name)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pods, err := podLister.Pods(service.Namespace).List(labels.SelectorFromValidatedSet(service.Spec.Selector))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
component := Component{
|
||||
Name: service.Name,
|
||||
Namespace: service.Namespace,
|
||||
SelfLink: service.SelfLink,
|
||||
Label: service.Spec.Selector,
|
||||
StartedAt: service.CreationTimestamp.Time,
|
||||
HealthyBackends: 0,
|
||||
TotalBackends: 0,
|
||||
}
|
||||
for _, v := range pods {
|
||||
component.TotalBackends++
|
||||
component.HealthyBackends++
|
||||
for _, c := range v.Status.ContainerStatuses {
|
||||
if !c.Ready {
|
||||
component.HealthyBackends--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return component, nil
|
||||
}
|
||||
|
||||
func GetSystemHealthStatus() (map[string]interface{}, error) {
|
||||
|
||||
status := make(map[string]interface{})
|
||||
|
||||
componentStatuses, err := componentStatusLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, cs := range componentStatuses {
|
||||
status[cs.Name] = cs.Conditions[0]
|
||||
}
|
||||
|
||||
// get kubesphere-system components
|
||||
systemComponentStatus, err := GetAllComponentsStatus()
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
for k, v := range systemComponentStatus {
|
||||
status[k] = v
|
||||
}
|
||||
// get node status
|
||||
nodes, err := nodeLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return status, nil
|
||||
}
|
||||
|
||||
nodeStatus := make(map[string]int)
|
||||
totalNodes := 0
|
||||
healthyNodes := 0
|
||||
for _, nodes := range nodes {
|
||||
totalNodes++
|
||||
for _, condition := range nodes.Status.Conditions {
|
||||
if condition.Type == coreV1.NodeReady && condition.Status == coreV1.ConditionTrue {
|
||||
healthyNodes++
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeStatus["totalNodes"] = totalNodes
|
||||
nodeStatus["healthyNodes"] = healthyNodes
|
||||
|
||||
status["nodes"] = nodeStatus
|
||||
|
||||
return status, nil
|
||||
|
||||
}
|
||||
|
||||
func GetAllComponentsStatus() (map[string]interface{}, error) {
|
||||
|
||||
status := make(map[string]interface{})
|
||||
|
||||
var err error
|
||||
|
||||
for _, ns := range constants.SystemNamespaces {
|
||||
|
||||
nsStatus := make(map[string]interface{})
|
||||
|
||||
services, err := serviceLister.Services(ns).List(labels.Everything())
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
component := Component{
|
||||
Name: service.Name,
|
||||
Namespace: service.Namespace,
|
||||
SelfLink: service.SelfLink,
|
||||
Label: service.Spec.Selector,
|
||||
StartedAt: service.CreationTimestamp.Time,
|
||||
HealthyBackends: 0,
|
||||
TotalBackends: 0,
|
||||
}
|
||||
|
||||
pods, err := podLister.Pods(ns).List(labels.SelectorFromValidatedSet(service.Spec.Selector))
|
||||
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, pod := range pods {
|
||||
component.TotalBackends++
|
||||
component.HealthyBackends++
|
||||
for _, c := range pod.Status.ContainerStatuses {
|
||||
if !c.Ready {
|
||||
component.HealthyBackends--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsStatus[service.Name] = component
|
||||
}
|
||||
|
||||
if len(nsStatus) > 0 {
|
||||
status[ns] = nsStatus
|
||||
}
|
||||
}
|
||||
|
||||
return status, err
|
||||
}
|
||||
29
pkg/models/hpa/hpa.go
Normal file
29
pkg/models/hpa/hpa.go
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere 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 hpa
|
||||
|
||||
import (
|
||||
"k8s.io/api/autoscaling/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func GetHPA(namespace, hpa string) (*v1.HorizontalPodAutoscaler, error) {
|
||||
return client.K8sClient().AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(hpa, metaV1.GetOptions{})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user