Skip to content

Commit e153a8c

Browse files
committed
Merge pull request #731 from bryk/generic-delete-backend
Backend for generic delete code
2 parents ac2203b + 55c9cfe commit e153a8c

File tree

19 files changed

+212
-47
lines changed

19 files changed

+212
-47
lines changed

src/app/backend/handler/apihandler.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type ApiHandler struct {
5252
client *client.Client
5353
heapsterClient HeapsterClient
5454
clientConfig clientcmd.ClientConfig
55+
verber common.ResourceVerber
5556
}
5657

5758
// Web-service filter function used for request and response logging.
@@ -83,7 +84,8 @@ func FormatResponseLog(resp *restful.Response, req *restful.Request) string {
8384
func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
8485
clientConfig clientcmd.ClientConfig) http.Handler {
8586

86-
apiHandler := ApiHandler{client, heapsterClient, clientConfig}
87+
verber := common.NewResourceVerber(client.RESTClient)
88+
apiHandler := ApiHandler{client, heapsterClient, clientConfig, verber}
8789
wsContainer := restful.NewContainer()
8890

8991
deployWs := new(restful.WebService)
@@ -270,6 +272,16 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
270272
Writes(resourceService.ServiceDetail{}))
271273
wsContainer.Add(servicesWs)
272274

275+
resourceVerberWs := new(restful.WebService)
276+
resourceVerberWs.Filter(wsLogger)
277+
resourceVerberWs.Path("/api/v1").
278+
Consumes(restful.MIME_JSON).
279+
Produces(restful.MIME_JSON)
280+
resourceVerberWs.Route(
281+
resourceVerberWs.DELETE("/{kind}/namespace/{namespace}/name/{name}").
282+
To(apiHandler.handleDeleteResource))
283+
wsContainer.Add(resourceVerberWs)
284+
273285
return wsContainer
274286
}
275287

@@ -527,6 +539,20 @@ func (apiHandler *ApiHandler) handleDeleteReplicationController(
527539
response.WriteHeader(http.StatusOK)
528540
}
529541

542+
func (apiHandler *ApiHandler) handleDeleteResource(
543+
request *restful.Request, response *restful.Response) {
544+
kind := request.PathParameter("kind")
545+
namespace := request.PathParameter("namespace")
546+
name := request.PathParameter("name")
547+
548+
if err := apiHandler.verber.Delete(kind, namespace, name); err != nil {
549+
handleInternalError(response, err)
550+
return
551+
}
552+
553+
response.WriteHeader(http.StatusOK)
554+
}
555+
530556
// Handles get Replication Controller Pods API call.
531557
func (apiHandler *ApiHandler) handleGetReplicationControllerPods(
532558
request *restful.Request, response *restful.Response) {

src/app/backend/resource/common/types.go

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,7 @@ import (
2121
"k8s.io/kubernetes/pkg/api/unversioned"
2222
)
2323

24-
type ResourceType string
25-
26-
const (
27-
ResourceTypeReplicaSet = "replicaset"
28-
ResourceTypeReplicationController = "replicationcontroller"
29-
)
30-
31-
func CreateObjectMeta(k8SObjectMeta api.ObjectMeta) ObjectMeta {
32-
return ObjectMeta{
33-
Name: k8SObjectMeta.Name,
34-
Namespace: k8SObjectMeta.Namespace,
35-
Labels: k8SObjectMeta.Labels,
36-
CreationTimestamp: k8SObjectMeta.CreationTimestamp,
37-
}
38-
}
39-
40-
func CreateTypeMeta(k8STypeMeta unversioned.TypeMeta) TypeMeta {
41-
return TypeMeta{
42-
Kind: k8STypeMeta.Kind,
43-
}
44-
}
45-
24+
// ObjectMeta is metadata about an instance of a resource.
4625
type ObjectMeta struct {
4726
// Name is unique within a namespace. Name is primarily intended for creation
4827
// idempotence and configuration definition.
@@ -83,7 +62,7 @@ type TypeMeta struct {
8362
// Servers may infer this from the endpoint the client submits requests to.
8463
// In smalllettercase.
8564
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
86-
Kind string `json:"kind,omitempty"`
65+
Kind ResourceKind `json:"kind,omitempty"`
8766
}
8867

8968
// Endpoint describes an endpoint that is host and a list of available ports for that host.
@@ -148,6 +127,49 @@ type Event struct {
148127
}
149128

150129
// Returns internal endpoint name for the given service properties, e.g.,
130+
// NewObjectMeta creates a new instance of ObjectMeta struct based on K8s object meta.
131+
func NewObjectMeta(k8SObjectMeta api.ObjectMeta) ObjectMeta {
132+
return ObjectMeta{
133+
Name: k8SObjectMeta.Name,
134+
Namespace: k8SObjectMeta.Namespace,
135+
Labels: k8SObjectMeta.Labels,
136+
CreationTimestamp: k8SObjectMeta.CreationTimestamp,
137+
}
138+
}
139+
140+
// NewTypeMeta creates new type mete for the resource kind.
141+
func NewTypeMeta(kind ResourceKind) TypeMeta {
142+
return TypeMeta{
143+
Kind: kind,
144+
}
145+
}
146+
147+
// ResourceKind is an unique name for each resource. It can used for API discovery and generic
148+
// code that does things based on the kind. For example, there may be a generic "deleter"
149+
// that based on resource kind, name and namespace deletes it.
150+
type ResourceKind string
151+
152+
// List of all resource kinds supported by the UI.
153+
const (
154+
ResourceKindReplicaSet = "replicaset"
155+
ResourceKindService = "service"
156+
ResourceKindDeployment = "deployment"
157+
ResourceKindPod = "pod"
158+
ResourceKindReplicationController = "replicationcontroller"
159+
)
160+
161+
// Mapping from resource kind to K8s apiserver API path. This is mostly pluralization, because
162+
// K8s apiserver uses plural paths and this project singular.
163+
// Must be kept in sync with the list of supported kinds.
164+
var kindToAPIPathMapping = map[string]string{
165+
ResourceKindService: "services",
166+
ResourceKindPod: "pods",
167+
ResourceKindReplicationController: "replicationcontrollers",
168+
ResourceKindDeployment: "deployments",
169+
ResourceKindReplicaSet: "replicasets",
170+
}
171+
172+
// GetInternalEndpoint returns internal endpoint name for the given service properties, e.g.,
151173
// "my-service.namespace 80/TCP" or "my-service 53/TCP,53/UDP".
152174
func GetInternalEndpoint(serviceName, namespace string, ports []api.ServicePort) Endpoint {
153175

@@ -165,7 +187,7 @@ func GetInternalEndpoint(serviceName, namespace string, ports []api.ServicePort)
165187
}
166188
}
167189

168-
// Gets human readable name for the given service ports list.
190+
// GetServicePorts returns human readable name for the given service ports list.
169191
func GetServicePorts(apiPorts []api.ServicePort) []ServicePort {
170192
var ports []ServicePort
171193
for _, port := range apiPorts {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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 (
18+
"errors"
19+
"fmt"
20+
21+
"k8s.io/kubernetes/pkg/client/restclient"
22+
)
23+
24+
// ResourceVerber is a struct responsible for doing common verb operations on resources, like
25+
// DELETE, PUT, UPDATE.
26+
type ResourceVerber struct {
27+
client RESTClient
28+
}
29+
30+
type RESTClient interface {
31+
Delete() *restclient.Request
32+
}
33+
34+
// NewResourceVerber creates a new resource verber that uses the given client for performing
35+
// operations.
36+
func NewResourceVerber(client RESTClient) ResourceVerber {
37+
return ResourceVerber{client}
38+
}
39+
40+
// Delete deletes the resource of the given kind in the given namespace with the given name.
41+
func (verber *ResourceVerber) Delete(kind string, namespace string, name string) error {
42+
apiPath, ok := kindToAPIPathMapping[kind]
43+
if !ok {
44+
return errors.New(fmt.Sprintf("Unknown resource kind: %s", kind))
45+
}
46+
47+
return verber.client.Delete().
48+
Namespace(namespace).
49+
Resource(apiPath).
50+
Name(name).
51+
Do().
52+
Error()
53+
}

src/app/backend/resource/deployment/deploymentlist.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ func getDeploymentList(deployments []extensions.Deployment,
116116

117117
deploymentList.Deployments = append(deploymentList.Deployments,
118118
Deployment{
119-
ObjectMeta: common.CreateObjectMeta(deployment.ObjectMeta),
120-
TypeMeta: common.CreateTypeMeta(deployment.TypeMeta),
119+
ObjectMeta: common.NewObjectMeta(deployment.ObjectMeta),
120+
TypeMeta: common.NewTypeMeta(common.ResourceKindDeployment),
121121
ContainerImages: replicationcontroller.GetContainerImages(&deployment.Spec.Template.Spec),
122122
Pods: podInfo,
123123
})

src/app/backend/resource/pod/podlist.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ func CreatePodList(pods []api.Pod, heapsterClient client.HeapsterClient) PodList
9292

9393
for _, pod := range pods {
9494
podDetail := Pod{
95-
ObjectMeta: common.CreateObjectMeta(pod.ObjectMeta),
96-
TypeMeta: common.CreateTypeMeta(pod.TypeMeta),
95+
ObjectMeta: common.NewObjectMeta(pod.ObjectMeta),
96+
TypeMeta: common.NewTypeMeta(common.ResourceKindPod),
9797
PodPhase: pod.Status.Phase,
9898
PodIP: pod.Status.PodIP,
9999
RestartCount: getRestartCount(pod),

src/app/backend/resource/replicaset/replicasetdetail.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ func getReplicaSetDetail(replicaSet *extensions.ReplicaSet, heapsterClient clien
8686
podInfo := getPodInfo(replicaSet, matchingPods)
8787

8888
return ReplicaSetDetail{
89-
ObjectMeta: common.CreateObjectMeta(replicaSet.ObjectMeta),
90-
TypeMeta: common.CreateTypeMeta(replicaSet.TypeMeta),
89+
ObjectMeta: common.NewObjectMeta(replicaSet.ObjectMeta),
90+
TypeMeta: common.NewTypeMeta(common.ResourceKindReplicaSet),
9191
ContainerImages: replicationcontroller.GetContainerImages(&replicaSet.Spec.Template.Spec),
9292
PodInfo: podInfo,
9393
PodList: pod.CreatePodList(matchingPods, heapsterClient),

src/app/backend/resource/replicaset/replicasetlist.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ func getReplicaSetList(replicaSets []extensions.ReplicaSet,
116116

117117
replicaSetList.ReplicaSets = append(replicaSetList.ReplicaSets,
118118
ReplicaSet{
119-
ObjectMeta: common.CreateObjectMeta(replicaSet.ObjectMeta),
120-
TypeMeta: common.CreateTypeMeta(replicaSet.TypeMeta),
119+
ObjectMeta: common.NewObjectMeta(replicaSet.ObjectMeta),
120+
TypeMeta: common.NewTypeMeta(common.ResourceKindReplicaSet),
121121
ContainerImages: replicationcontroller.GetContainerImages(&replicaSet.Spec.Template.Spec),
122122
Pods: podInfo,
123123
})

src/app/backend/resource/replicationcontroller/replicationcontrollerdetail.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ func GetReplicationControllerDetail(client k8sClient.Interface, heapsterClient c
8585
}
8686

8787
replicationControllerDetail := &ReplicationControllerDetail{
88-
ObjectMeta: common.CreateObjectMeta(replicationController.ObjectMeta),
89-
TypeMeta: common.CreateTypeMeta(replicationController.TypeMeta),
88+
ObjectMeta: common.NewObjectMeta(replicationController.ObjectMeta),
89+
TypeMeta: common.NewTypeMeta(common.ResourceKindReplicationController),
9090
LabelSelector: replicationController.Spec.Selector,
9191
PodInfo: getReplicationPodInfo(replicationController, pods.Items),
9292
ServiceList: resourceService.ServiceList{Services: make([]resourceService.Service, 0)},

src/app/backend/resource/replicationcontroller/replicationcontrollerlist.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ func getReplicationControllerList(replicationControllers []api.ReplicationContro
135135

136136
replicationControllerList.ReplicationControllers = append(replicationControllerList.ReplicationControllers,
137137
ReplicationController{
138-
ObjectMeta: common.CreateObjectMeta(replicationController.ObjectMeta),
139-
TypeMeta: common.CreateTypeMeta(replicationController.TypeMeta),
138+
ObjectMeta: common.NewObjectMeta(replicationController.ObjectMeta),
139+
TypeMeta: common.NewTypeMeta(common.ResourceKindReplicationController),
140140
Pods: podInfo,
141141
ContainerImages: GetContainerImages(&replicationController.Spec.Template.Spec),
142142
InternalEndpoints: internalEndpoints,

src/app/backend/resource/service/servicecommon.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import (
2323
// ToService returns api service object based on kubernetes service object
2424
func ToService(service *api.Service) Service {
2525
return Service{
26-
ObjectMeta: common.CreateObjectMeta(service.ObjectMeta),
27-
TypeMeta: common.CreateTypeMeta(service.TypeMeta),
26+
ObjectMeta: common.NewObjectMeta(service.ObjectMeta),
27+
TypeMeta: common.NewTypeMeta(common.ResourceKindService),
2828
InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports),
2929
// TODO(maciaszczykm): Fill ExternalEndpoints with data.
3030
Selector: service.Spec.Selector,
@@ -35,8 +35,8 @@ func ToService(service *api.Service) Service {
3535
// ToServiceDetails returns api service object based on kubernetes service object
3636
func ToServiceDetail(service *api.Service) ServiceDetail {
3737
return ServiceDetail{
38-
ObjectMeta: common.CreateObjectMeta(service.ObjectMeta),
39-
TypeMeta: common.CreateTypeMeta(service.TypeMeta),
38+
ObjectMeta: common.NewObjectMeta(service.ObjectMeta),
39+
TypeMeta: common.NewTypeMeta(common.ResourceKindService),
4040
InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports),
4141
// TODO(maciaszczykm): Fill ExternalEndpoints with data.
4242
Selector: service.Spec.Selector,

0 commit comments

Comments
 (0)