Initial commit

This commit is contained in:
jeff
2019-03-07 17:08:54 +08:00
commit 47bf8820f4
2817 changed files with 960937 additions and 0 deletions

View 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
View 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)
}

View 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)
}

View 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)
}

View 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)
}

View 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)
}

View 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)
//}

View 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)
}

View 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)
}

View 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)
}

View 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)
}

View 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)
}

View 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
}
}

View 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
}

View 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)
}

View 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)
}