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

Feature/add kubernetes pod resource #254

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
79 changes: 54 additions & 25 deletions src/backend/controllers/base/parambuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,8 @@ type ParamBuilderController struct {
ResultHandlerController
}

// TODO: 需要重构成独立的Controller,参考Django的generic views设计
func (c *ParamBuilderController) BuildQueryParam() *common.QueryParam {
pageNo := c.Input().Get("pageNo")
pageSize := c.Input().Get("pageSize")
if pageNo == "" {
pageNo = strconv.Itoa(defaultPageNo)
}

if pageSize == "" {
pageSize = strconv.Itoa(defaultPageSize)
}

no, err := strconv.ParseInt(pageNo, 10, 64)
// pageNo must bigger than zero.
if err != nil || no < 1 {
c.AbortBadRequest("Invalid pageNo in query.")
}
// pageSize must bigger than zero.
size, err := strconv.ParseInt(pageSize, 10, 64)
if err != nil || size < 1 {
c.AbortBadRequest("Invalid pageSize in query.")
}
no, size := c.buildPageParam()

qmap := map[string]interface{}{}
deletedStr := c.Input().Get("deleted")
Expand Down Expand Up @@ -73,12 +53,61 @@ func (c *ParamBuilderController) BuildQueryParam() *common.QueryParam {
relate = c.Input().Get("relate")
}

return &common.QueryParam{PageNo: no,
return &common.QueryParam{
PageNo: no,
PageSize: size,
Query: qmap,
Sortby: snaker.CamelToSnake(c.Input().Get("sortby")),
Relate: relate}
}

func (c *ParamBuilderController) BuildKubernetesQueryParam() *common.QueryParam {
no, size := c.buildPageParam()

qmap := map[string]interface{}{}

filter := c.Input().Get("filter")
if filter != "" {
filters := strings.Split(filter, ",")
for _, param := range filters {
params := strings.Split(param, "=")
if len(params) != 2 {
continue
}
qmap[params[0]] = params[1]
}
}

return &common.QueryParam{
PageNo: no,
PageSize: size,
Query: qmap,
Sortby: snaker.CamelToSnake(c.Input().Get("sortby")),
Relate: relate,
LabelSelector: c.Input().Get("filter")}
Sortby: c.Input().Get("sortby"),
LabelSelector: c.Input().Get("labelSelector")}
}

func (c *ParamBuilderController) buildPageParam() (no int64, size int64) {
pageNo := c.Input().Get("pageNo")
pageSize := c.Input().Get("pageSize")
if pageNo == "" {
pageNo = strconv.Itoa(defaultPageNo)
}

if pageSize == "" {
pageSize = strconv.Itoa(defaultPageSize)
}

no, err := strconv.ParseInt(pageNo, 10, 64)
// pageNo must bigger than zero.
if err != nil || no < 1 {
c.AbortBadRequest("Invalid pageNo in query.")
}
// pageSize must bigger than zero.
size, err = strconv.ParseInt(pageSize, 10, 64)
if err != nil || size < 1 {
c.AbortBadRequest("Invalid pageSize in query.")
}
return
}

func (c *ParamBuilderController) GetIDFromURL() int64 {
Expand Down
25 changes: 18 additions & 7 deletions src/backend/controllers/kubernetes/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package proxy

import (
"encoding/json"
"strconv"

meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -100,7 +101,7 @@ func (c *KubeProxyController) GetNames() {
// @Success 200 {object} success
// @router / [get]
func (c *KubeProxyController) List() {
param := c.BuildQueryParam()
param := c.BuildKubernetesQueryParam()
cluster := c.Ctx.Input.Param(":cluster")
namespace := c.Ctx.Input.Param(":namespace")
kind := c.Ctx.Input.Param(":kind")
Expand Down Expand Up @@ -179,21 +180,31 @@ func (c *KubeProxyController) Update() {
// @Param kind path string true "the resource kind"
// @Param namespace path string true "the namespace want to delete"
// @Param name path string true "the name want to delete"
// @Param deleteOptions body string false "the kubernetes delete options"
// @Param force query bool false "force to delete the resource from etcd."
// @Success 200 {string} delete success!
// @router /:name [delete]
func (c *KubeProxyController) Delete() {
cluster := c.Ctx.Input.Param(":cluster")
namespace := c.Ctx.Input.Param(":namespace")
name := c.Ctx.Input.Param(":name")
kind := c.Ctx.Input.Param(":kind")
var deleteOptions meta_v1.DeleteOptions
err := json.Unmarshal(c.Ctx.Input.RequestBody, &deleteOptions)
if err != nil {
c.AbortBadRequestFormat("deleteOptions")
force := c.Input().Get("force")
defaultPropagationPolicy := meta_v1.DeletePropagationBackground
defaultDeleteOptions := meta_v1.DeleteOptions{
PropagationPolicy: &defaultPropagationPolicy,
}
if force != "" {
forceBool, err := strconv.ParseBool(force)
if err != nil {
c.AbortBadRequestFormat("force")
}
if forceBool {
var gracePeriodSeconds int64 = 0
defaultDeleteOptions.GracePeriodSeconds = &gracePeriodSeconds
}
}
kubeClient := c.KubeClient(cluster)
err = kubeClient.Delete(kind, namespace, name, &deleteOptions)
err := kubeClient.Delete(kind, namespace, name, &defaultDeleteOptions)
if err != nil {
logs.Error("Delete kubernetes resource (%s:%s:%s) from cluster (%s) error. %v", kind, namespace, name, cluster, err)
c.HandleError(err)
Expand Down
11 changes: 11 additions & 0 deletions src/backend/resources/proxy/proxy.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package proxy

import (
"sort"

"k8s.io/apimachinery/pkg/util/json"

"github.com/Qihoo360/wayne/src/backend/client"
Expand Down Expand Up @@ -28,6 +30,10 @@ func GetPage(kubeClient client.ResourceHandler, kind string, namespace string, q
commonObjs = append(commonObjs, commonObj)
}

sort.Slice(commonObjs, func(i, j int) bool {
return commonObjs[j].GetProperty(dataselector.NameProperty).Compare(commonObjs[i].GetProperty(dataselector.NameProperty)) == 1
})

return dataselector.DataSelectPage(commonObjs, q), nil
}

Expand All @@ -36,6 +42,7 @@ func GetNames(kubeClient client.ResourceHandler, kind string, namespace string)
if err != nil {
return nil, err
}

commonObjs := make([]response.NamesObject, 0)
for _, obj := range objs {
objByte, err := json.Marshal(obj)
Expand All @@ -52,5 +59,9 @@ func GetNames(kubeClient client.ResourceHandler, kind string, namespace string)
})
}

sort.Slice(commonObjs, func(i, j int) bool {
return commonObjs[i].Name < commonObjs[j].Name
})

return commonObjs, nil
}
3 changes: 3 additions & 0 deletions src/frontend/src/app/admin/admin-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import { AutoscaleComponent } from './autoscale/autoscale.component';
import { TrashAutoscaleComponent } from './autoscale/trash-autoscale/trash-autoscale.component';
import { AutoscaletplComponent } from './autoscaletpl/autoscaletpl.component';
import { TrashAutoscaletplComponent } from './autoscaletpl/trash-autoscaletpl/trash-autoscaletpl.component';
import { KubePodComponent } from './kubernetes/pod/kube-pod.component';


const routes: Routes = [
Expand Down Expand Up @@ -148,6 +149,8 @@ const routes: Routes = [
{path: 'kubernetes/deployment/:cluster', component: KubeDeploymentComponent},
{path: 'kubernetes/namespace', component: KubeNamespaceComponent},
{path: 'kubernetes/namespace/:cluster', component: KubeNamespaceComponent},
{path: 'kubernetes/pod', component: KubePodComponent},
{path: 'kubernetes/pod/:cluster', component: KubePodComponent},
...ADMINROUTES
]
}
Expand Down
4 changes: 3 additions & 1 deletion src/frontend/src/app/admin/admin.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { CreateEditAutoscaletplComponent } from './autoscaletpl/create-edit-auto
import { ListAutoscaletplComponent } from './autoscaletpl/list-autoscaletpl/list-autoscaletpl.component';
import { TrashAutoscaletplComponent } from './autoscaletpl/trash-autoscaletpl/trash-autoscaletpl.component';
import { SidenavModule } from './sidenav/sidenav.module';
import { KubePodModule } from './kubernetes/pod/kube-pod.module';

@NgModule({
imports: [
Expand Down Expand Up @@ -88,7 +89,8 @@ import { SidenavModule } from './sidenav/sidenav.module';
IngressTplModule,
KubeDeploymentModule,
TplDetailModule,
SidenavModule
SidenavModule,
KubePodModule,
],
providers: [
AdminAuthCheckGuard,
Expand Down
49 changes: 49 additions & 0 deletions src/frontend/src/app/admin/kubernetes/pod/kube-pod.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<div class="clr-row">
<div class="clr-col-lg-12 clr-col-md-12 clr-col-sm-12 clr-col-xs-12">
<div class="table-search">
<div class="table-search-left">
<button class="wayne-button normal" (click)="createResource()">
{{'ADMIN.KUBERNETES.POD.CREATE' | translate}}
</button>
<button class="wayne-button normal" (click)="retrieveResource()">
{{'ADMIN.KUBERNETES.ACTION.REFRESH' | translate}}
</button>
<wayne-filter-box (confirm)="onConfirmEvent()" (cancel)="onCancelEvent()">
<wayne-checkbox-group [(ngModel)]="showList">
<wayne-checkbox value="name">{{'ADMIN.KUBERNETES.POD.LIST.NAME' | translate}}</wayne-checkbox>
<wayne-checkbox value="label">{{'ADMIN.KUBERNETES.POD.LIST.LABEL' | translate}}</wayne-checkbox>
<wayne-checkbox value="images">{{'ADMIN.KUBERNETES.POD.LIST.IMAGES' | translate}}</wayne-checkbox>
<wayne-checkbox value="status"> {{'ADMIN.KUBERNETES.POD.LIST.STATUS' | translate}}</wayne-checkbox>
<wayne-checkbox value="podIP">{{'ADMIN.KUBERNETES.POD.LIST.PODIP' | translate}}</wayne-checkbox>
<wayne-checkbox value="node">{{'ADMIN.KUBERNETES.POD.LIST.NODE' | translate}}</wayne-checkbox>
<wayne-checkbox value="restartCount">{{'ADMIN.KUBERNETES.POD.LIST.RESTARTCOUNT' | translate}}</wayne-checkbox>
<wayne-checkbox value="age">{{'ADMIN.KUBERNETES.POD.LIST.AGE' | translate}}</wayne-checkbox>
</wayne-checkbox-group>
</wayne-filter-box>
<label for="namespace_name" class="clr-col-md-3">{{'ADMIN.KUBERNETES.LABEL.NAMESPACE' | translate}}</label>
<wayne-select [(ngModel)]="namespace" (change)="retrieveResource()"
searchable
name="namespace_name"
[placeholder]="'PLACEHOLDER.CHOOSE' | translate"
style="margin-left: 12px;">
<wayne-option *ngFor="let ns of namespaces" [value]="ns">{{ns}}</wayne-option>
</wayne-select>
</div>
</div>

<wayne-list-pod
[resources]="resources"
[showState]="showState"
(delete)="onDeleteResourceEvent($event)"
(edit)="onEditResourceEvent($event)"
[page]="pageState.page"
(paginate)="retrieveResource($event)">
</wayne-list-pod>
</div>
</div>
<deletion-dialog (outputObj)="confirmDeleteEvent($event)"></deletion-dialog>
<wayne-ace-editor (createOutputObj)="onCreateResourceEvent($event)" (outputObj)="onSaveResourceEvent($event)"></wayne-ace-editor>
<wayne-float-window value="{{ cluster }}">
<wayne-float-window-item *ngFor="let cluster of clusters" [value]="cluster"
(click)="jumpToHref(cluster)"></wayne-float-window-item>
</wayne-float-window>
63 changes: 63 additions & 0 deletions src/frontend/src/app/admin/kubernetes/pod/kube-pod.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ConfirmationDialogService } from '../../../shared/confirmation-dialog/confirmation-dialog.service';
import { MessageHandlerService } from '../../../shared/message-handler/message-handler.service';
import { ClusterService } from '../../../shared/client/v1/cluster.service';
import { AuthService } from '../../../shared/auth/auth.service';
import { AceEditorComponent } from '../../../shared/ace-editor/ace-editor.component';
import { ListPodComponent } from './list-pod/list-pod.component';
import { KubernetesClient } from '../../../shared/client/v1/kubernetes/kubernetes';
import { KubeResourcePod } from '../../../shared/shared.const';
import { KubernetesNamespacedResource } from '../../../shared/base/kubernetes-namespaced/kubernetes-namespaced-resource';
import { DeletionDialogComponent } from '../../../shared/deletion-dialog/deletion-dialog.component';

const showState = {
'name': {hidden: false},
'label': {hidden: false},
'images': {hidden: false},
'status': {hidden: false},
'podIP': {hidden: false},
'node': {hidden: false},
'restartCount': {hidden: false},
'age': {hidden: false},
};

@Component({
selector: 'wayne-kube-pod',
templateUrl: './kube-pod.component.html'
})

export class KubePodComponent extends KubernetesNamespacedResource implements OnInit, OnDestroy {
@ViewChild(ListPodComponent)
listResourceComponent: ListPodComponent;

@ViewChild(AceEditorComponent)
aceEditorModal: AceEditorComponent;

@ViewChild(DeletionDialogComponent)
deletionDialogComponent: DeletionDialogComponent;

constructor(public kubernetesClient: KubernetesClient,
public route: ActivatedRoute,
public router: Router,
public clusterService: ClusterService,
public authService: AuthService,
public messageHandlerService: MessageHandlerService) {
super(kubernetesClient, route, router, clusterService, authService, messageHandlerService);
super.registResourceType('pod');
super.registKubeResource(KubeResourcePod);
super.registShowSate(showState);
}

ngOnInit() {
super.ngOnInit();
}

ngOnDestroy(): void {
super.ngOnDestroy();
}




}
29 changes: 29 additions & 0 deletions src/frontend/src/app/admin/kubernetes/pod/kube-pod.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../shared/shared.module';
import { ReactiveFormsModule } from '@angular/forms';
import { KubePodComponent } from './kube-pod.component';
import { ListPodComponent } from './list-pod/list-pod.component';
import { KubernetesClient } from '../../../shared/client/v1/kubernetes/kubernetes';
import { DeletionDialogModule } from '../../../shared/deletion-dialog/deletion-dialog.module';

@NgModule({
imports: [
SharedModule,
ReactiveFormsModule,
DeletionDialogModule
],
providers: [
KubernetesClient
],
exports: [
KubePodComponent,
ListPodComponent
],
declarations: [
KubePodComponent,
ListPodComponent
]
})

export class KubePodModule {
}
Loading