Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Openapi add get_pod_list #378

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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