Skip to content

Commit 6cbbb2a

Browse files
committed
Merge pull request #768 from bryk/namespace-selector
Backend for namespace selection
2 parents dbc9dc2 + e17e669 commit 6cbbb2a

File tree

19 files changed

+394
-164
lines changed

19 files changed

+394
-164
lines changed

src/app/backend/handler/apihandler.go

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"log"
2020
"net/http"
2121
"strconv"
22+
"strings"
2223

2324
restful "github.com/emicklei/go-restful"
2425
// TODO(maciaszczykm): Avoid using dot-imports.
@@ -131,6 +132,10 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
131132
apiV1Ws.GET("/replicationcontroller").
132133
To(apiHandler.handleGetReplicationControllerList).
133134
Writes(ReplicationControllerList{}))
135+
apiV1Ws.Route(
136+
apiV1Ws.GET("/replicationcontroller/{namespace}").
137+
To(apiHandler.handleGetReplicationControllerList).
138+
Writes(ReplicationControllerList{}))
134139
apiV1Ws.Route(
135140
apiV1Ws.GET("/replicationcontroller/{namespace}/{replicationController}").
136141
To(apiHandler.handleGetReplicationControllerDetail).
@@ -151,11 +156,19 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
151156
apiV1Ws.GET("/workload").
152157
To(apiHandler.handleGetWorkloads).
153158
Writes(workload.Workloads{}))
159+
apiV1Ws.Route(
160+
apiV1Ws.GET("/workload/{namespace}").
161+
To(apiHandler.handleGetWorkloads).
162+
Writes(workload.Workloads{}))
154163

155164
apiV1Ws.Route(
156165
apiV1Ws.GET("/replicaset").
157166
To(apiHandler.handleGetReplicaSets).
158167
Writes(replicaset.ReplicaSetList{}))
168+
apiV1Ws.Route(
169+
apiV1Ws.GET("/replicaset/{namespace}").
170+
To(apiHandler.handleGetReplicaSets).
171+
Writes(replicaset.ReplicaSetList{}))
159172
apiV1Ws.Route(
160173
apiV1Ws.GET("/replicaset/{namespace}/{replicaSet}").
161174
To(apiHandler.handleGetReplicaSetDetail).
@@ -165,6 +178,10 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
165178
apiV1Ws.GET("/pod").
166179
To(apiHandler.handleGetPods).
167180
Writes(pod.PodList{}))
181+
apiV1Ws.Route(
182+
apiV1Ws.GET("/pod/{namespace}").
183+
To(apiHandler.handleGetPods).
184+
Writes(pod.PodList{}))
168185
apiV1Ws.Route(
169186
apiV1Ws.GET("/pod/{namespace}/{pod}").
170187
To(apiHandler.handleGetPodDetail).
@@ -174,7 +191,10 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
174191
apiV1Ws.GET("/deployment").
175192
To(apiHandler.handleGetDeployments).
176193
Writes(deployment.DeploymentList{}))
177-
194+
apiV1Ws.Route(
195+
apiV1Ws.GET("/deployment/{namespace}").
196+
To(apiHandler.handleGetDeployments).
197+
Writes(deployment.DeploymentList{}))
178198
apiV1Ws.Route(
179199
apiV1Ws.GET("/deployment/{namespace}/{deployment}").
180200
To(apiHandler.handleGetDeploymentDetail).
@@ -184,6 +204,10 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
184204
apiV1Ws.GET("/daemonset").
185205
To(apiHandler.handleGetDaemonSetList).
186206
Writes(daemonset.DaemonSetList{}))
207+
apiV1Ws.Route(
208+
apiV1Ws.GET("/daemonset/{namespace}").
209+
To(apiHandler.handleGetDaemonSetList).
210+
Writes(daemonset.DaemonSetList{}))
187211
apiV1Ws.Route(
188212
apiV1Ws.GET("/daemonset/{namespace}/{daemonSet}").
189213
To(apiHandler.handleGetDaemonSetDetail).
@@ -230,6 +254,10 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
230254
apiV1Ws.GET("/service").
231255
To(apiHandler.handleGetServiceList).
232256
Writes(resourceService.ServiceList{}))
257+
apiV1Ws.Route(
258+
apiV1Ws.GET("/service/{namespace}").
259+
To(apiHandler.handleGetServiceList).
260+
Writes(resourceService.ServiceList{}))
233261
apiV1Ws.Route(
234262
apiV1Ws.GET("/service/{namespace}/{service}").
235263
To(apiHandler.handleGetServiceDetail).
@@ -244,7 +272,8 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
244272

245273
// Handles get service list API call.
246274
func (apiHandler *ApiHandler) handleGetServiceList(request *restful.Request, response *restful.Response) {
247-
result, err := resourceService.GetServiceList(apiHandler.client)
275+
namespace := parseNamespacePathParameter(request)
276+
result, err := resourceService.GetServiceList(apiHandler.client, namespace)
248277
if err != nil {
249278
handleInternalError(response, err)
250279
return
@@ -361,7 +390,8 @@ func (apiHandler *ApiHandler) handleGetAvailableProcotols(request *restful.Reque
361390
func (apiHandler *ApiHandler) handleGetReplicationControllerList(
362391
request *restful.Request, response *restful.Response) {
363392

364-
result, err := GetReplicationControllerList(apiHandler.client)
393+
namespace := parseNamespacePathParameter(request)
394+
result, err := GetReplicationControllerList(apiHandler.client, namespace)
365395
if err != nil {
366396
handleInternalError(response, err)
367397
return
@@ -374,7 +404,8 @@ func (apiHandler *ApiHandler) handleGetReplicationControllerList(
374404
func (apiHandler *ApiHandler) handleGetWorkloads(
375405
request *restful.Request, response *restful.Response) {
376406

377-
result, err := workload.GetWorkloads(apiHandler.client, apiHandler.heapsterClient)
407+
namespace := parseNamespacePathParameter(request)
408+
result, err := workload.GetWorkloads(apiHandler.client, apiHandler.heapsterClient, namespace)
378409
if err != nil {
379410
handleInternalError(response, err)
380411
return
@@ -387,7 +418,8 @@ func (apiHandler *ApiHandler) handleGetWorkloads(
387418
func (apiHandler *ApiHandler) handleGetReplicaSets(
388419
request *restful.Request, response *restful.Response) {
389420

390-
result, err := replicaset.GetReplicaSetList(apiHandler.client)
421+
namespace := parseNamespacePathParameter(request)
422+
result, err := replicaset.GetReplicaSetList(apiHandler.client, namespace)
391423
if err != nil {
392424
handleInternalError(response, err)
393425
return
@@ -416,7 +448,8 @@ func (apiHandler *ApiHandler) handleGetReplicaSetDetail(
416448
func (apiHandler *ApiHandler) handleGetDeployments(
417449
request *restful.Request, response *restful.Response) {
418450

419-
result, err := deployment.GetDeploymentList(apiHandler.client)
451+
namespace := parseNamespacePathParameter(request)
452+
result, err := deployment.GetDeploymentList(apiHandler.client, namespace)
420453
if err != nil {
421454
handleInternalError(response, err)
422455
return
@@ -445,7 +478,8 @@ func (apiHandler *ApiHandler) handleGetDeploymentDetail(
445478
func (apiHandler *ApiHandler) handleGetPods(
446479
request *restful.Request, response *restful.Response) {
447480

448-
result, err := pod.GetPodList(apiHandler.client, apiHandler.heapsterClient)
481+
namespace := parseNamespacePathParameter(request)
482+
result, err := pod.GetPodList(apiHandler.client, apiHandler.heapsterClient, namespace)
449483
if err != nil {
450484
handleInternalError(response, err)
451485
return
@@ -652,7 +686,7 @@ func handleInternalError(response *restful.Response, err error) {
652686
func (apiHandler *ApiHandler) handleGetDaemonSetList(
653687
request *restful.Request, response *restful.Response) {
654688

655-
namespace := request.PathParameter("namespace")
689+
namespace := parseNamespacePathParameter(request)
656690
result, err := daemonset.GetDaemonSetList(apiHandler.client, namespace)
657691
if err != nil {
658692
handleInternalError(response, err)
@@ -697,3 +731,19 @@ func (apiHandler *ApiHandler) handleDeleteDaemonSet(
697731

698732
response.WriteHeader(http.StatusOK)
699733
}
734+
735+
// parseNamespacePathParameter parses namespace selector for list pages in path paramater.
736+
// The namespace selector is a comma separated list of namespaces that are trimmed.
737+
// No namespaces means "view all user namespaces", i.e., everything except kube-system.
738+
func parseNamespacePathParameter(request *restful.Request) *common.NamespaceQuery {
739+
namespace := request.PathParameter("namespace")
740+
namespaces := strings.Split(namespace, ",")
741+
var nonEmptyNamespaces []string
742+
for _, n := range namespaces {
743+
n = strings.Trim(n, " ")
744+
if len(n) > 0 {
745+
nonEmptyNamespaces = append(nonEmptyNamespaces, n)
746+
}
747+
}
748+
return common.NewNamespaceQuery(nonEmptyNamespaces)
749+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2015 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package common
16+
17+
import "k8s.io/kubernetes/pkg/api"
18+
19+
// NamespaceQuery is a query for namespaces of a list of objects.
20+
// There's three cases:
21+
// 1. No namespace selected: this means "user namespaces" query, i.e., all except kube-system
22+
// 2. Single namespace selected: this allows for optimizations when querying backends
23+
// 3. More than one namespace selected: resources from all namespaces are queried and then
24+
// filtered here.
25+
type NamespaceQuery struct {
26+
namespaces []string
27+
}
28+
29+
// NewSameNamespaceQuery creates new namespace query that queries single namespace.
30+
func NewSameNamespaceQuery(namespace string) *NamespaceQuery {
31+
return &NamespaceQuery{[]string{namespace}}
32+
}
33+
34+
// NewNamespaceQuery creates new query for given namespaces.
35+
func NewNamespaceQuery(namespaces []string) *NamespaceQuery {
36+
return &NamespaceQuery{namespaces}
37+
}
38+
39+
// ToRequestParam returns K8s API namespace query for list of objects from this namespaces.
40+
// This is an optimization to query for single namespace if one was selected and for all
41+
// namespaces otherwise.
42+
func (n *NamespaceQuery) ToRequestParam() string {
43+
if len(n.namespaces) == 1 {
44+
return n.namespaces[0]
45+
}
46+
return api.NamespaceAll
47+
}
48+
49+
// Matches returns true when the given namespace matches this query.
50+
func (n *NamespaceQuery) Matches(namespace string) bool {
51+
if len(n.namespaces) == 0 {
52+
return namespace != api.NamespaceSystem
53+
}
54+
55+
for _, queryNamespace := range n.namespaces {
56+
if namespace == queryNamespace {
57+
return true
58+
}
59+
}
60+
return false
61+
}

0 commit comments

Comments
 (0)