Skip to content

Commit

Permalink
Merge pull request #378 from wilhelmguo/feature/openapi_add_get_pod_list
Browse files Browse the repository at this point in the history
Openapi add get_pod_list
  • Loading branch information
wilhelmguo authored Mar 25, 2019
2 parents 2ca7c3f + eeb7933 commit a6773d5
Show file tree
Hide file tree
Showing 8 changed files with 392 additions and 144 deletions.
66 changes: 1 addition & 65 deletions src/backend/controllers/kubernetes/pod/pod.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
package pod

import (
"fmt"
"net/http"
"sync"

"github.com/Qihoo360/wayne/src/backend/client"
"github.com/Qihoo360/wayne/src/backend/client/api"
"github.com/Qihoo360/wayne/src/backend/common"
"github.com/Qihoo360/wayne/src/backend/controllers/base"
"github.com/Qihoo360/wayne/src/backend/models"
erroresult "github.com/Qihoo360/wayne/src/backend/models/response/errors"
"github.com/Qihoo360/wayne/src/backend/resources/pod"
"github.com/Qihoo360/wayne/src/backend/util/logs"
)
Expand All @@ -23,7 +18,6 @@ func (c *KubePodController) URLMapping() {
c.Mapping("PodStatistics", c.PodStatistics)
c.Mapping("List", c.List)
c.Mapping("Terminal", c.Terminal)
c.Mapping("GetEvent", c.GetEvent)
}

func (c *KubePodController) Prepare() {
Expand Down Expand Up @@ -108,65 +102,7 @@ func (c *KubePodController) List() {
resourceName := c.Input().Get("name")
param := c.BuildKubernetesQueryParam()
manager := c.Manager(cluster)
var result *common.Page
var err error
switch resourceType {
case api.ResourceNameDeployment:
result, err = pod.GetPodsByDeploymentPage(manager.KubeClient, namespace, resourceName, param)
case api.ResourceNameStatefulSet:
result, err = pod.GetRelatedPodByType(manager.KubeClient, namespace, resourceName, api.ResourceNameStatefulSet, param)
case api.ResourceNameDaemonSet:
result, err = pod.GetRelatedPodByType(manager.KubeClient, namespace, resourceName, api.ResourceNameDaemonSet, param)
case api.ResourceNameJob:
result, err = pod.GetRelatedPodByType(manager.KubeClient, namespace, resourceName, api.ResourceNameJob, param)
case api.ResourceNamePod:
result, err = pod.GetPodPage(manager.KubeClient, namespace, resourceName, param)
default:
err = &erroresult.ErrorResult{
Code: http.StatusBadRequest,
Msg: fmt.Sprintf("Unsupported resource type (%s). ", resourceType),
}
}
if err != nil {
logs.Error("Get kubernetes pod by type error.", cluster, namespace, resourceType, resourceName, err)
c.HandleError(err)
return
}
c.Success(result)
}

// @Title GetPodEvent
// @Description Get Pod Event by resource type and name
// @Param pageNo query int false "the page current no"
// @Param pageSize query int false "the page size"
// @Param type query string true "the query type. deployments, statefulsets, daemonsets,cronjobs"
// @Param name query string true "the query resource name."
// @Success 200 {object} models.Deployment success
// @router /events/namespaces/:namespace/clusters/:cluster [get]
func (c *KubePodController) GetEvent() {
cluster := c.Ctx.Input.Param(":cluster")
namespace := c.Ctx.Input.Param(":namespace")
resourceType := c.Input().Get("type")
resourceName := c.Input().Get("name")
param := c.BuildKubernetesQueryParam()
manager := c.Manager(cluster)
var result *common.Page
var err error
switch resourceType {
case api.ResourceNameDeployment:
result, err = pod.GetPodsByDeploymentPage(manager.KubeClient, namespace, resourceName, param)
case api.ResourceNameStatefulSet:
result, err = pod.GetRelatedPodByType(manager.KubeClient, namespace, resourceName, api.ResourceNameStatefulSet, param)
case api.ResourceNameDaemonSet:
result, err = pod.GetRelatedPodByType(manager.KubeClient, namespace, resourceName, api.ResourceNameDaemonSet, param)
case api.ResourceNameCronJob:
result, err = pod.GetRelatedPodByType(manager.KubeClient, namespace, resourceName, api.ResourceNameJob, param)
default:
err = &erroresult.ErrorResult{
Code: http.StatusBadRequest,
Msg: fmt.Sprintf("Unsupported resource type (%s). ", resourceType),
}
}
result, err := pod.GetPodListPageByType(manager.KubeClient, namespace, resourceName, resourceType, param)
if err != nil {
logs.Error("Get kubernetes pod by type error.", cluster, namespace, resourceType, resourceName, err)
c.HandleError(err)
Expand Down
1 change: 1 addition & 0 deletions src/backend/controllers/openapi/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const (
UpgradeDeploymentAction = "UPGRADE_DEPLOYMENT"
ScaleDeploymentAction = "SCALE_DEPLOYMENT"
RestartDeploymentAction = "RESTART_DEPLOYMENT"
GetPodListAction = "GET_POD_LIST"
PermissionPrefix = "OPENAPI_"
)

Expand Down
163 changes: 163 additions & 0 deletions src/backend/controllers/openapi/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import (
"fmt"
"net/http"
"strings"
"time"

"k8s.io/apimachinery/pkg/labels"

"github.com/Qihoo360/wayne/src/backend/client"
"github.com/Qihoo360/wayne/src/backend/client/api"
"github.com/Qihoo360/wayne/src/backend/models"
"github.com/Qihoo360/wayne/src/backend/models/response"
"github.com/Qihoo360/wayne/src/backend/resources/common"
"github.com/Qihoo360/wayne/src/backend/resources/pod"
"github.com/Qihoo360/wayne/src/backend/util/logs"
)
Expand Down Expand Up @@ -44,6 +49,50 @@ type PodInfoFromIPParam struct {
Cluster string `json:"cluster"`
}

// swagger:parameters PodListParam
type PodListParam struct {
// Wayne 的 namespace 名称,必须与 Name 同时存在或者不存在
// in: query
// Required: false
Namespace string `json:"namespace"`
// 资源名称,必须与 Namespace 同时存在或者不存在
// in: query
// Required: false
Name string `json:"name"`
// 资源类型:daemonsets,deployments,cronjobs,statefulsets
// in: query
// Required: true
Type api.ResourceName `json:"type"`
}

// An array of the pod.
// swagger:response respPodInfoList
type respPodInfoList struct {
// in: body
// Required: true
Body struct {
response.ResponseBase
RespListInfo []*respListInfo `json:"list"`
}
}

type respListInfo struct {
Cluster string `json:"cluster,omitempty"`
ResourceName string `json:"resourceName,omitempty"`
// Wayne namespace 名称
Namespace string `json:"namespace,omitempty"`
Pods []respPodInfo `json:"pods"`
}

type respPodInfo struct {
Name string `json:"name,omitempty"`
Namespace string `json:"namespace,omitempty"`
NodeName string `json:"nodeName,omitempty"`
PodIp string `json:"podIp,omitempty"`
State string `json:"state,omitempty"`
StartTime time.Time `json:"startTime,omitempty"`
}

// swagger:route GET /get_pod_info pod PodInfoParam
//
// 用于获取线上所有 pod 中包含请求条件中 labelSelector 指定的特定 label 的 pod
Expand Down Expand Up @@ -139,3 +188,117 @@ func (c *OpenAPIController) GetPodInfoFromIP() {
c.HandleResponse(podList.Body)

}

// swagger:route GET /get_pod_list pod PodListParam
//
// 用于根据资源类型获取所有机房Pod列表
//
// 返回 Pod 信息
// 需要绑定全局 apikey 使用。
//
// Responses:
// 200: respPodInfoList
// 401: responseState
// 500: responseState
// @router /get_pod_list [get]
func (c *OpenAPIController) GetPodList() {
if !c.CheckoutRoutePermission(GetPodListAction) {
return
}
if c.APIKey.Type != models.GlobalAPIKey {
c.AddErrorAndResponse("You can only use global APIKey in this action!", http.StatusUnauthorized)
return
}
podList := respPodInfoList{}
podList.Body.Code = http.StatusOK
params := PodListParam{c.GetString("namespace"), c.GetString("name"), c.GetString("type")}
if params.Type == "" {
c.AddErrorAndResponse("Invalid type parameter:must required!", http.StatusBadRequest)
return
}
if (params.Name == "" && params.Namespace != "") || (params.Name != "" && params.Namespace == "") {
c.AddErrorAndResponse("Namespace and Name must exist or not exist at the same time!", http.StatusBadRequest)
return
}
var ns *models.Namespace
var err error
if params.Namespace != "" {
ns, err = models.NamespaceModel.GetByName(params.Namespace)
if err != nil {
c.AddErrorAndResponse(fmt.Sprintf("Get Namespace by name (%s) error!%v", params.Namespace, err), http.StatusBadRequest)
return
}
}

managers := client.Managers()
managers.Range(func(key, value interface{}) bool {
manager := value.(*client.ClusterManager)
// if Name and Namespace empty,return all pods
if params.Name == "" && params.Namespace == "" {
objs, err := manager.KubeClient.List(params.Type, "", labels.Everything().String())
if err != nil {
c.AddError(fmt.Sprintf("List all resource error.cluster:%s,type:%s, %v",
manager.Cluster.Name, params.Type, err))
return true
}

for _, obj := range objs {
commonObj, err := common.ToBaseObject(obj)
if err != nil {
c.AddError(fmt.Sprintf("ToBaseObject error.cluster:%s,type:%s, %v",
manager.Cluster.Name, params.Type, err))
return true
}
podListResp, err := buildPodListResp(manager, params.Namespace, commonObj.Namespace, commonObj.Name, params.Type)
if err != nil {
c.AddError(fmt.Sprintf("buildPodListResp error.cluster:%s,type:%s, %v",
manager.Cluster.Name, params.Type, err))
return true
}
if len(podListResp.Pods) > 0 {
podList.Body.RespListInfo = append(podList.Body.RespListInfo, podListResp)
}
}
return true
}

podListResp, err := buildPodListResp(manager, params.Namespace, ns.KubeNamespace, params.Name, params.Type)
if err != nil {
c.AddError(fmt.Sprintf("buildPodListResp error.cluster:%s,type:%s,namespace:%s,name:%s %v",
manager.Cluster.Name, ns.KubeNamespace, params.Name, params.Type, err))
return true
}
if len(podListResp.Pods) > 0 {
podList.Body.RespListInfo = append(podList.Body.RespListInfo, podListResp)
}

return true
})

c.HandleResponse(podList.Body)
}

func buildPodListResp(manager *client.ClusterManager, namespace, kubeNamespace, resourceName string, resourceType api.ResourceName) (*respListInfo, error) {
pods, err := pod.GetPodListByType(manager.KubeClient, kubeNamespace, resourceName, resourceType)
if err != nil {
return nil, err
}

listInfo := &respListInfo{
Cluster: manager.Cluster.Name,
ResourceName: resourceName,
Namespace: namespace,
}

for _, kubePod := range pods {
listInfo.Pods = append(listInfo.Pods, respPodInfo{
Name: kubePod.Name,
Namespace: kubePod.Namespace,
NodeName: kubePod.Spec.NodeName,
PodIp: kubePod.Status.PodIP,
State: pod.GetPodStatus(kubePod),
StartTime: kubePod.CreationTimestamp.Time,
})
}
return listInfo, nil
}
27 changes: 27 additions & 0 deletions src/backend/resources/common/common.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package common

import (
"encoding/json"

"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

// TODO convert runtime.Object to real type
Expand All @@ -27,3 +30,27 @@ type Object struct {
Spec interface{} `json:"spec,omitempty"`
Status interface{} `json:"status,omitempty"`
}

// ReplicaSet ensures that a specified number of pod replicas are running at any given time.
type BaseObject struct {
metav1.TypeMeta `json:",inline"`

// If the Labels of a ReplicaSet are empty, they are defaulted to
// be the same as the Pod(s) that the ReplicaSet manages.
// Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty"`
}

func ToBaseObject(obj runtime.Object) (*BaseObject, error) {
objByte, err := json.Marshal(obj)
if err != nil {
return nil, err
}
var commonObj BaseObject
err = json.Unmarshal(objByte, &commonObj)
if err != nil {
return nil, err
}
return &commonObj, nil
}
Loading

0 comments on commit a6773d5

Please sign in to comment.