Skip to content

Commit

Permalink
Do not attempt service instance deletion if it has bindings
Browse files Browse the repository at this point in the history
Fixes #2149
  • Loading branch information
jeff-phillips-18 committed Sep 22, 2017
1 parent 1dae20b commit b5dcf95
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 75 deletions.
1 change: 1 addition & 0 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ <h1>JavaScript Required</h1>
<script src="scripts/controllers/modals/linkService.js"></script>
<script src="scripts/controllers/modals/jenkinsfileExamplesModal.js"></script>
<script src="scripts/controllers/modals/aboutComputeUnitsModal.js"></script>
<script src="scripts/controllers/modals/warningModal.js"></script>
<script src="scripts/controllers/about.js"></script>
<script src="scripts/controllers/commandLine.js"></script>
<script src="scripts/controllers/createPersistentVolumeClaim.js"></script>
Expand Down
26 changes: 26 additions & 0 deletions app/scripts/controllers/modals/warningModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';
/* jshint unused: false */

/**
* @ngdoc function
* @name openshiftConsole.controller:WarningModalController
* @description
* # WarningModalController
* Controller of the openshiftConsole
*/
angular.module('openshiftConsole')
.controller('WarningModalController', function($scope,
$uibModalInstance,
modalConfig) {
// content supplied in the following forms:
// heading: modalConfig.title
// content: strongMessage (strong text)
// content: modalConfig.message (plain text ONLY, no user input)
// content: modalConfig.messageMarkup (pre-sanitized, see _.escape() or _.template('<%- %>') )
// button: closeButtonText
_.extend($scope, modalConfig);

$scope.close = function() {
$uibModalInstance.dismiss('cancel');
};
});
119 changes: 80 additions & 39 deletions app/scripts/services/serviceInstances.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,105 @@
angular.module("openshiftConsole")
.factory("ServiceInstancesService", function($filter,
$uibModal,
BindingService,
CatalogService,
DataService,
NotificationsService) {

function deprovision(apiObject) {
var doDeprovision = function (apiObject) {
var getErrorDetails = $filter('getErrorDetails');
var modalInstance;

var modalScope = {
alerts: {
deprovision: {
type: 'error',
message: 'Service \'' + apiObject.spec.serviceClassName + '\' will be deleted and no longer available.'
}
},
detailsMarkup: 'Delete Service?',
kind: apiObject.kind,
displayName: apiObject.metadata.name,
okButtonText: 'Delete',
okButtonClass: 'btn-danger',
cancelButtonText: 'Cancel'
cancelButtonText: 'Cancel',
delete: function() {
modalInstance.close('delete');
}
};

// TODO: we probably have to handle bindings in here.
// either:
// - automatically remove the bindings
// - tell the user they must manually unbind before continue
return $uibModal.open({
modalInstance = $uibModal.open({
animation: true,
templateUrl: 'views/modals/confirm.html',
templateUrl: 'views/modals/delete-resource.html',
controller: 'ConfirmModalController',
resolve: {
modalConfig: function() {
return modalScope;
}
}
})
.result.then(function() {
});

return modalInstance.result.then(function() {
NotificationsService.hideNotification("deprovision-service-error");

return DataService.delete({
group: 'servicecatalog.k8s.io',
resource: 'serviceinstances'
},
apiObject.metadata.name,
{ namespace: apiObject.metadata.namespace },
{ propagationPolicy: null
}) // TODO - remove once this is resolved https://github.com/kubernetes-incubator/service-catalog/issues/942
.then(function() {
NotificationsService.addNotification({
type: "success",
message: "Successfully deleted provisioned service " + apiObject.metadata.name + "."
});
}, function(err) {
NotificationsService.addNotification({
id: "deprovision-service-error",
type: "error",
message: "An error occurred while deleting provisioned service " + apiObject.metadata.name + ".",
details: getErrorDetails(err)
});
var context = {namespace: apiObject.metadata.namespace};
var resource = {
group: 'servicecatalog.k8s.io',
resource: 'serviceinstances'
};

// TODO - remove once this is resolved https://github.com/kubernetes-incubator/service-catalog/issues/942
var opts = {
propagationPolicy: null
};

return DataService.delete(resource, apiObject.metadata.name, context, opts).then(function() {
NotificationsService.addNotification({
type: "success",
message: "Successfully deleted provisioned service " + apiObject.metadata.name + "."
});
}, function(err) {
NotificationsService.addNotification({
id: "deprovision-service-error",
type: "error",
message: "An error occurred while deleting provisioned service " + apiObject.metadata.name + ".",
details: getErrorDetails(err)
});
});
});
}
};

var showUnableToDeprovisionDialog = function() {
return $uibModal.open({
animation: true,
templateUrl: 'views/modals/warning.html',
controller: 'WarningModalController',
resolve: {
modalConfig: function() {
return {
title: "Unable to Deprovision",
strongMessage: "This service cannot be deprovisioned because it has bindings.",
message: "You must delete all bindings from the service before you can deprovision it."
};
}
}
});
};

var deprovision = function (apiObject) {
var context = {namespace: apiObject.metadata.namespace};
var resource = {
group: 'servicecatalog.k8s.io',
resource: 'serviceinstancecredentials'
};

if (CatalogService.SERVICE_CATALOG_ENABLED) {
DataService.list(resource, context, function (bindings) {
var serviceBindings = BindingService.getBindingsForResource(bindings.by('metadata.name'), apiObject);
if (serviceBindings.length > 0) {
showUnableToDeprovisionDialog();
} else {
doDeprovision(apiObject);
}
}, function() {
doDeprovision(apiObject);
});
} else {
doDeprovision(apiObject);
}
};

return {
deprovision: deprovision
Expand Down
14 changes: 14 additions & 0 deletions app/views/modals/warning.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="modal-resource-action">
<div class="modal-body">
<h1>
<span class="pficon pficon-warning-triangle-o"></span>
{{title}}
</h1>
<p class="strong" ng-if="strongMessage">{{strongMessage}}</p>
<p ng-if="message">{{message}}</p>
<p ng-if="messageMarkup" ng-bind-html="messageMarkup"></p>
</div>
<div class="modal-footer">
<button class="btn btn-lg btn-default" type="button" ng-click="close()">{{closeButtonText || 'Close'}}</button>
</div>
</div>
104 changes: 68 additions & 36 deletions dist/scripts/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ return _.get(e, "metadata.name");
return _.get(e, "metadata.uid");
}, G = function() {
return _.size(P.deploymentConfigs) + _.size(P.vanillaReplicationControllers) + _.size(P.deployments) + _.size(P.vanillaReplicaSets) + _.size(P.statefulSets) + _.size(P.monopods) + _.size(P.state.serviceInstances);
}, K = function() {
return _.size(P.filteredDeploymentConfigs) + _.size(P.filteredReplicationControllers) + _.size(P.filteredDeployments) + _.size(P.filteredReplicaSets) + _.size(P.filteredStatefulSets) + _.size(P.filteredMonopods) + _.size(P.filteredServiceInstances);
}, W = function() {
P.size = G(), P.filteredSize = K();
return _.size(P.filteredDeploymentConfigs) + _.size(P.filteredReplicationControllers) + _.size(P.filteredDeployments) + _.size(P.filteredReplicaSets) + _.size(P.filteredStatefulSets) + _.size(P.filteredMonopods) + _.size(P.filteredServiceInstances);
}, K = function() {
P.size = G(), P.filteredSize = W();
var e = 0 === P.size, t = P.deploymentConfigs && P.replicationControllers && P.deployments && P.replicaSets && P.statefulSets && P.pods && P.state.serviceInstances;
V.expandAll = t && 1 === P.size, P.showGetStarted = t && e, P.showLoading = !t && e, P.everythingFiltered = !e && !P.filteredSize, P.hidePipelineOtherResources = "pipeline" === P.viewBy && (P.filterActive || _.isEmpty(P.pipelineBuildConfigs));
}, Q = function(e) {
Expand Down Expand Up @@ -119,7 +119,7 @@ case "name":
return !_.isEmpty(V.filterKeywords);
}
}, ie = function() {
P.filteredDeploymentConfigs = re(P.deploymentConfigs), P.filteredReplicationControllers = re(P.vanillaReplicationControllers), P.filteredDeployments = re(P.deployments), P.filteredReplicaSets = re(P.vanillaReplicaSets), P.filteredStatefulSets = re(P.statefulSets), P.filteredMonopods = re(P.monopods), P.filteredPipelineBuildConfigs = re(P.pipelineBuildConfigs), P.filteredServiceInstances = re(V.orderedServiceInstances), P.filterActive = oe(), Z(), W();
P.filteredDeploymentConfigs = re(P.deploymentConfigs), P.filteredReplicationControllers = re(P.vanillaReplicationControllers), P.filteredDeployments = re(P.deployments), P.filteredReplicaSets = re(P.vanillaReplicaSets), P.filteredStatefulSets = re(P.statefulSets), P.filteredMonopods = re(P.monopods), P.filteredPipelineBuildConfigs = re(P.pipelineBuildConfigs), P.filteredServiceInstances = re(V.orderedServiceInstances), P.filterActive = oe(), Z(), K();
}, se = n.project + "/overview/view-by";
P.viewBy = localStorage.getItem(se) || "app", e.$watch(function() {
return P.viewBy;
Expand Down Expand Up @@ -315,7 +315,7 @@ _.isEmpty(o) || (t = t.concat(o));
qe(), ze();
}, Ge = function() {
_.each(P.deploymentConfigs, Me);
}, Ke = function() {
}, We = function() {
if (V.builds && P.buildConfigs) {
P.recentPipelinesByBuildConfig = {}, V.recentBuildsByBuildConfig = {}, V.recentPipelinesByDeploymentConfig = {};
var e = {};
Expand All @@ -330,7 +330,7 @@ return i.sortBuilds(e, !0);
return i.sortBuilds(e, !0);
}), Ge();
}
}, We = function() {
}, Ke = function() {
k.setQuotaNotifications(V.quotas, V.clusterQuotas, n.project);
};
P.clearFilter = function() {
Expand Down Expand Up @@ -395,7 +395,7 @@ resource: "deployments"
}, a, function(e) {
I = e.by("metadata.uid"), P.deployments = _.sortBy(I, "metadata.name"), Ee(), Ae(P.deployments), Ae(P.vanillaReplicaSets), we(P.deployments), Qe(), ie(), h.log("deployments (subscribe)", P.deploymentsByUID);
})), Ye.push(l.watch("builds", a, function(e) {
V.builds = e.by("metadata.name"), Ke(), h.log("builds (subscribe)", V.builds);
V.builds = e.by("metadata.name"), We(), h.log("builds (subscribe)", V.builds);
})), Ye.push(l.watch({
group: "apps",
resource: "statefulsets"
Expand All @@ -415,7 +415,7 @@ P.routes = e.by("metadata.name"), Be(), h.log("routes (subscribe)", P.routes);
poll: R,
pollInterval: 6e4
})), Ye.push(l.watch("buildConfigs", a, function(e) {
P.buildConfigs = e.by("metadata.name"), Fe(), He(), Ke(), ie(), h.log("buildconfigs (subscribe)", P.buildConfigs);
P.buildConfigs = e.by("metadata.name"), Fe(), He(), We(), ie(), h.log("buildconfigs (subscribe)", P.buildConfigs);
}, {
poll: R,
pollInterval: 6e4
Expand All @@ -434,12 +434,12 @@ T = e.by("metadata.name"), m.buildDockerRefMapForImageStreams(T, V.imageStreamIm
poll: R,
pollInterval: 6e4
})), Ye.push(l.watch("resourcequotas", a, function(e) {
V.quotas = e.by("metadata.name"), We();
V.quotas = e.by("metadata.name"), Ke();
}, {
poll: !0,
pollInterval: 6e4
})), Ye.push(l.watch("appliedclusterresourcequotas", a, function(e) {
V.clusterQuotas = e.by("metadata.name"), We();
V.clusterQuotas = e.by("metadata.name"), Ke();
}, {
poll: !0,
pollInterval: 6e4
Expand Down Expand Up @@ -4277,52 +4277,80 @@ controller: !0
});
}
};
}), angular.module("openshiftConsole").factory("ServiceInstancesService", [ "$filter", "$uibModal", "DataService", "NotificationsService", function(e, t, n, a) {
return {
deprovision: function(r) {
var o = e("getErrorDetails"), i = {
alerts: {
deprovision: {
type: "error",
message: "Service '" + r.spec.serviceClassName + "' will be deleted and no longer available."
}
},
detailsMarkup: "Delete Service?",
}), angular.module("openshiftConsole").factory("ServiceInstancesService", [ "$filter", "$uibModal", "BindingService", "CatalogService", "DataService", "NotificationsService", function(e, t, n, a, r, o) {
var i = function(n) {
var a, i = e("getErrorDetails"), s = {
kind: n.kind,
displayName: n.metadata.name,
okButtonText: "Delete",
okButtonClass: "btn-danger",
cancelButtonText: "Cancel"
cancelButtonText: "Cancel",
delete: function() {
a.close("delete");
}
};
return t.open({
return (a = t.open({
animation: !0,
templateUrl: "views/modals/confirm.html",
templateUrl: "views/modals/delete-resource.html",
controller: "ConfirmModalController",
resolve: {
modalConfig: function() {
return i;
return s;
}
}
}).result.then(function() {
return a.hideNotification("deprovision-service-error"), n.delete({
})).result.then(function() {
o.hideNotification("deprovision-service-error");
var e = {
namespace: n.metadata.namespace
}, t = {
group: "servicecatalog.k8s.io",
resource: "serviceinstances"
}, r.metadata.name, {
namespace: r.metadata.namespace
}, {
}, a = {
propagationPolicy: null
}).then(function() {
a.addNotification({
};
return r.delete(t, n.metadata.name, e, a).then(function() {
o.addNotification({
type: "success",
message: "Successfully deleted provisioned service " + r.metadata.name + "."
message: "Successfully deleted provisioned service " + n.metadata.name + "."
});
}, function(e) {
a.addNotification({
o.addNotification({
id: "deprovision-service-error",
type: "error",
message: "An error occurred while deleting provisioned service " + r.metadata.name + ".",
details: o(e)
message: "An error occurred while deleting provisioned service " + n.metadata.name + ".",
details: i(e)
});
});
});
}, s = function() {
return t.open({
animation: !0,
templateUrl: "views/modals/warning.html",
controller: "WarningModalController",
resolve: {
modalConfig: function() {
return {
title: "Unable to Deprovision",
strongMessage: "This service cannot be deprovisioned because it has bindings.",
message: "You must delete all bindings from the service before you can deprovision it."
};
}
}
});
};
return {
deprovision: function(e) {
var t = {
namespace: e.metadata.namespace
}, o = {
group: "servicecatalog.k8s.io",
resource: "serviceinstancecredentials"
};
a.SERVICE_CATALOG_ENABLED ? r.list(o, t, function(t) {
n.getBindingsForResource(t.by("metadata.name"), e).length > 0 ? s() : i(e);
}, function() {
i(e);
}) : i(e);
}
};
} ]), angular.module("openshiftConsole").controller("LandingPageController", [ "$scope", "$rootScope", "AuthService", "Catalog", "Constants", "DataService", "Navigate", "NotificationsService", "RecentlyViewedServiceItems", "GuidedTourService", "HTMLService", "$timeout", "$q", "$routeParams", "$location", function(e, t, n, a, r, o, i, s, c, l, u, d, p, m, f) {
Expand Down Expand Up @@ -8666,6 +8694,10 @@ t.close("ok");
e.ok = function() {
t.close("ok");
};
} ]), angular.module("openshiftConsole").controller("WarningModalController", [ "$scope", "$uibModalInstance", "modalConfig", function(e, t, n) {
_.extend(e, n), e.close = function() {
t.dismiss("cancel");
};
} ]), angular.module("openshiftConsole").controller("AboutController", [ "$scope", "AuthService", "Constants", function(e, t, n) {
t.withUser(), e.version = {
master: {
Expand Down
Loading

0 comments on commit b5dcf95

Please sign in to comment.