Skip to content

Commit

Permalink
Merge pull request #329 from floreks/delete-service
Browse files Browse the repository at this point in the history
Added option to delete services related to replication controller while deleting RC
  • Loading branch information
bryk committed Feb 3, 2016
2 parents 04453c0 + 24fce07 commit a320d52
Show file tree
Hide file tree
Showing 11 changed files with 411 additions and 72 deletions.
9 changes: 8 additions & 1 deletion src/app/backend/apihandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,20 @@ func (apiHandler *ApiHandler) handleUpdateReplicasCount(
}

// Handles delete Replication Controller API call.
// TODO(floreks): there has to be some kind of transaction here
func (apiHandler *ApiHandler) handleDeleteReplicationController(
request *restful.Request, response *restful.Response) {

namespace := request.PathParameter("namespace")
replicationController := request.PathParameter("replicationController")
deleteServices, err := strconv.ParseBool(request.QueryParameter("deleteServices"))
if err != nil {
handleInternalError(response, err)
return
}

if err := DeleteReplicationControllerWithPods(apiHandler.client, namespace, replicationController); err != nil {
if err := DeleteReplicationController(apiHandler.client, namespace,
replicationController, deleteServices); err != nil {
handleInternalError(response, err)
return
}
Expand Down
45 changes: 45 additions & 0 deletions src/app/backend/replicationcontrollercommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package main
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
Expand Down Expand Up @@ -103,3 +104,47 @@ func getReplicationControllerPodInfo(replicationController *api.ReplicationContr

return result
}

// Transforms simple selector map to labels.Selector object that can be used when querying for
// object.
func toLabelSelector(selector map[string]string) (labels.Selector, error) {
labelSelector, err := extensions.LabelSelectorAsSelector(&extensions.LabelSelector{MatchLabels: selector})

if err != nil {
return nil, err
}

return labelSelector, nil
}

// Based on given selector returns list of services that are candidates for deletion.
// Services are matched by replication controllers' label selector. They are deleted if given
// label selector is targeting only 1 replication controller.
func getServicesForDeletion(client client.Interface, labelSelector labels.Selector,
namespace string) ([]api.Service, error) {

replicationControllers, err := client.ReplicationControllers(namespace).List(unversioned.ListOptions{
LabelSelector: unversioned.LabelSelector{labelSelector},
FieldSelector: unversioned.FieldSelector{fields.Everything()},
})
if err != nil {
return nil, err
}

// if label selector is targeting only 1 replication controller
// then we can delete services targeted by this label selector,
// otherwise we can not delete any services so just return empty list
if len(replicationControllers.Items) != 1 {
return []api.Service{}, nil
}

services, err := client.Services(namespace).List(unversioned.ListOptions{
LabelSelector: unversioned.LabelSelector{labelSelector},
FieldSelector: unversioned.FieldSelector{fields.Everything()},
})
if err != nil {
return nil, err
}

return services.Items, nil
}
48 changes: 44 additions & 4 deletions src/app/backend/replicationcontrollerdetail.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,20 @@ func GetReplicationControllerDetail(client client.Interface, heapsterClient Heap
return replicationControllerDetail, nil
}

// TODO(floreks): This should be transactional to make sure that RC will not be deleted without
// TODO(floreks): Should related services be deleted also?
// Deletes replication controller with given name in given namespace and related pods
func DeleteReplicationControllerWithPods(client client.Interface, namespace, name string) error {
// TODO(floreks): This should be transactional to make sure that RC will not be deleted without pods
// Deletes replication controller with given name in given namespace and related pods.
// Also deletes services related to replication controller if deleteServices is true.
func DeleteReplicationController(client client.Interface, namespace, name string,
deleteServices bool) error {

log.Printf("Deleting %s replication controller from %s namespace", name, namespace)

if deleteServices {
if err := DeleteReplicationControllerServices(client, namespace, name); err != nil {
return err
}
}

pods, err := getRawReplicationControllerPods(client, namespace, name)
if err != nil {
return err
Expand All @@ -212,6 +220,38 @@ func DeleteReplicationControllerWithPods(client client.Interface, namespace, nam
return nil
}

// Deletes services related to replication controller with given name in given namespace.
func DeleteReplicationControllerServices(client client.Interface, namespace, name string) error {
log.Printf("Deleting services related to %s replication controller from %s namespace", name,
namespace)

replicationController, err := client.ReplicationControllers(namespace).Get(name)
if err != nil {
return err
}

labelSelector, err := toLabelSelector(replicationController.Spec.Selector)
if err != nil {
return err
}

services, err := getServicesForDeletion(client, labelSelector, namespace)
if err != nil {
return err
}

for _, service := range services {
if err := client.Services(namespace).Delete(service.Name); err != nil {
return err
}
}

log.Printf("Successfully deleted services related to %s replication controller from %s namespace",
name, namespace)

return nil
}

// Updates number of replicas in Replication Controller based on Replication Controller Spec
func UpdateReplicasCount(client client.Interface, namespace, name string,
replicationControllerSpec *ReplicationControllerSpec) error {
Expand Down
7 changes: 7 additions & 0 deletions src/app/externs/backendapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ backendApi.ReplicationControllerDetail;
*/
backendApi.ReplicationControllerSpec;

/**
* @typedef {{
* deleteServices: boolean
* }}
*/
backendApi.DeleteReplicationControllerSpec;

/**
* @typedef {{
* name: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ <h4 class="md-title">Delete Replication Controller</h4>
Delete replication controller {{::ctrl.replicationController}} in namespace {{::ctrl.namespace}}.<br>
Pods managed by the replication controller will be also deleted.
</div>
<md-checkbox ng-model="ctrl.deleteServices" class="kd-deletedialog-services-checkbox">
Delete related services
<md-icon class="material-icons kd-deletedialog-info-icon">
info
<md-tooltip>Services with label selector matching only this replication controller
will be deleted</md-tooltip>
</md-icon>
</md-checkbox>
<md-dialog-actions>
<md-button class="md-primary" ng-click="ctrl.cancel()">Cancel</md-button>
<md-button class="md-primary" ng-click="ctrl.remove()">Delete</md-button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

@import '../variables';

md-checkbox {
&.kd-deletedialog-services-checkbox {
margin: $baseline-grid 0 0 $baseline-grid;
}
}

.kd-deletedialog-info-icon {
font-size: $subhead-font-size-base;
height: $subhead-font-size-base;
margin-left: $baseline-grid / 2;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export default class DeleteReplicationControllerDialogController {
/** @export {string} */
this.namespace = namespace;

/** @export {boolean} */
this.deleteServices = false;

/** @private {!md.$dialog} */
this.mdDialog_ = $mdDialog;

Expand All @@ -50,7 +53,15 @@ export default class DeleteReplicationControllerDialogController {
remove() {
let resource = getReplicationControllerDetailsResource(
new StateParams(this.namespace, this.replicationController), this.resource_);
resource.remove(() => { this.mdDialog_.hide(); }, () => { this.mdDialog_.cancel(); });

/** @type {!backendApi.DeleteReplicationControllerSpec} */
let deleteReplicationControllerSpec = {
deleteServices: this.deleteServices,
};

resource.remove(
deleteReplicationControllerSpec, () => { this.mdDialog_.hide(); },
() => { this.mdDialog_.cancel(); });
}

/**
Expand Down
63 changes: 0 additions & 63 deletions src/test/backend/replicasetcommon_test.go

This file was deleted.

Loading

0 comments on commit a320d52

Please sign in to comment.