Skip to content
This repository has been archived by the owner on May 19, 2020. It is now read-only.

Allowing service destroyer to unbind apps and warn users #68

Merged
merged 4 commits into from
Aug 17, 2015
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
63 changes: 51 additions & 12 deletions static/app/cloudfoundry.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(function() {
// CloudFoundry Service
angular.module('cfdeck').service('$cloudfoundry', function($http, $location, $log) {
angular.module('cfdeck').service('$cloudfoundry', function($http, $location, $log, $q) {

// Declare variables for passing data via this service
var orgs, activeOrg;
Expand All @@ -24,15 +24,15 @@
.then(returnAuthStatus, returnAuthStatus);
};

this.isAuthorized = function() {
this.isAuthorized = function() {
return this.getAuthStatus()
.then(function(status) {
if (status == "authorized") {
return true;
}
return false;
});
};
.then(function(status) {
if (status == "authorized") {
return true;
}
return false;
});
};

// Get organizations
this.getOrgs = function() {
Expand Down Expand Up @@ -112,14 +112,40 @@
});
};

// Delete a service instance
this.deleteServiceInstance = function(service) {
// Delete unbound service Instance
var deleteUnboundServiceInstance = function(service) {
return $http.delete(service.metadata.url)
.then(function(response) {
return response.data;
}, function(response) {
return response.data;
});
});
};


// Delete bound service instance, by undinding all services first
var deleteBoundServiceInstance = function(service) {
return $http.get(service.entity.service_bindings_url)
.then(function(response) {
// Collect promises
var requestsPromises = response.data.resources.map(function(boundService) {
return $http.delete(boundService.metadata.url)
});
// Run promises and then delete service instance
return $q.all(requestsPromises)
.then(function() {
return deleteUnboundServiceInstance(service)
});
});
};

// Delete a service instance
this.deleteServiceInstance = function(service, bound) {
if (!bound) {
return deleteUnboundServiceInstance(service);
} else {
return deleteBoundServiceInstance(service);
}
};

// Given an org guid attempts to find the active org data stored in the service
Expand Down Expand Up @@ -193,6 +219,19 @@
});
};

// Get service credentials
this.getServiceCredentials = function(service) {
// Look for service binding guid
return $http.get(service.entity.service_bindings_url)
.then(function(response) {
// Find the service binding that is attached to the current space
return response.data.resources.filter(function(boundService) {
return boundService.entity.space_guid === service.space_guid;
})[0].entity.credentials;
});
};


// Tells whether the web app should poll for newer app statuses.
// Useful for when we are in the middle of updating the app status ourselves and we don't
// want a poll to interrupt the UI.
Expand Down
47 changes: 33 additions & 14 deletions static/app/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
$scope.space = space;
};
var renderServices = function(services) {
console.log(services);
$scope.services = services;
};
// Show a specific tab
Expand Down Expand Up @@ -128,24 +127,43 @@
app.controller('AppCtrl', function($scope, $cloudfoundry, $routeParams, $interval, MenuData) {
loadOrg(MenuData, $routeParams, $cloudfoundry, $scope);

var getServiceCredentials = function(service) {
$cloudfoundry.getServiceCredentials(service)
.then(function (credentials) {
service.credentials = credentials;
});
}


//Show the available services
var loadServices = function(boundSevices) {
$cloudfoundry.getSpaceServices($routeParams['spaceguid']).then(function(services) {
// Add additional info to the services if they are bound
$scope.availableServices = services.map(function(service) {
boundSevices.forEach(function(boundService) {
if (boundService.guid == service.metadata.guid) {
// Add the bound service info to services
service.boundService = boundService;
getServiceCredentials(service)
};
});
return service;
});
$scope.servicesLoaded = true;
});
};


// Inject Math functions into the view.
$scope.Math = window.Math;
var renderAppSummary = function(appSummary) {
// Only render while we are not updating an app ourselves.
if ($cloudfoundry.getPollAppStatusProperty() === true) {
$scope.appSummary = appSummary;
// Show the available services
$cloudfoundry.getSpaceServices($routeParams['spaceguid']).then(function(services) {
// Add a tag to services if they are bound
$scope.availableServices = services.map(function(service) {
$scope.appSummary.services.forEach(function(boundService) {
if (boundService.guid == service.metadata.guid) {
service.boundService = boundService;
};
});
return service;
});
});
// Load services only when, they haven't been collected
if (!$scope.servicesLoaded) {
loadServices($scope.appSummary.services);
}
}
};
var renderAppStats = function(appStats) {
Expand Down Expand Up @@ -207,7 +225,7 @@
service_instance_guid: service.metadata.guid,
app_guid: $routeParams['appguid']
}).then(function(response) {

$scope.servicesLoaded = false;
$cloudfoundry.getAppSummary($routeParams['appguid']).then(renderAppSummary);
$scope.disableServiceBinder = false;
});
Expand All @@ -219,6 +237,7 @@
service_instance_guid: service.boundService.guid,
app_guid: $routeParams['appguid']
}, function(response) {
$scope.servicesLoaded = false;
$cloudfoundry.getAppSummary($routeParams['appguid']).then(renderAppSummary);
$scope.disableServiceBinder = false;
});
Expand Down
40 changes: 19 additions & 21 deletions static/app/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,29 @@
app.directive('serviceDestroyer', function($cloudfoundry) {
return {
templateUrl: 'app/views/partials/service_destroyer.html',
restrict: 'A',
scope: {
service: "=service",
},
controller: function($scope) {
$scope.view = {
status: 'unconfirmed',
disableButton: false,

};
$scope.view.showDestroyer = function(state) {
$scope.view.status = state;
};
$scope.view.deleteService = function(service) {
$cloudfoundry.deleteServiceInstance(service)
$scope.view.deleteService = function(service, bound) {
$scope.view.disableButton = true;
$cloudfoundry.deleteServiceInstance(service, bound)
.then(function(response) {
if (response.code === undefined) {
$scope.view.status = "success";
$scope.view.message = "Deleted!";
$scope.showTab('serviceInstances')
} else if (response.code === 10006) {
$scope.view.status = "error";
$scope.view.message = "This service is bound to one or more apps";
$scope.view.status = "boundError";
} else {
$scope.view.status = "error";
$scope.view.message = "Unknown error, try refreshing."
}
})
}
$scope.view.disableButton = false;
});
};
}
};
Expand All @@ -41,18 +39,18 @@
templateUrl: 'app/views/partials/header.html',
restrict: 'A',
controller: function($scope) {
// Render the given name of the user on the page
// Render the given name of the user on the page
var renderName = function(name) {
$scope.givenName = name;
};
$cloudfoundry.isAuthorized()
.then(function(authorized) {
$scope.authorized = authorized;
if (authorized == true) {
// Load the given name of the logged in user.
$uaa.getUserInfoGivenName().then(renderName);
}
});
$cloudfoundry.isAuthorized()
.then(function(authorized) {
$scope.authorized = authorized;
if (authorized == true) {
// Load the given name of the logged in user.
$uaa.getUserInfoGivenName().then(renderName);
}
});
}
};
});
Expand Down
32 changes: 25 additions & 7 deletions static/app/views/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ <h3 class="panel-title">Actions</h3>
<div ng-switch="appSummary.state">
<div ng-switch-when='STARTED'>
<button type="button" ladda="restarting" class="btn btn-warning" ng-disabled="stopping"
mwl-confirm title="Warning!" message="Are you sure you want to interrupt connectivity to the application?"
on-confirm="restartApp(appSummary)" confirm-button-type="danger" cancel-button-type="default">
mwl-confirm title="Warning!" message="Are you sure you want to interrupt connectivity to the application?"
on-confirm="restartApp(appSummary)" confirm-button-type="danger"
cancel-button-type="default">
Restart
</button>
<button type="button" ladda="stopping" class="btn btn-danger" ng-disabled="restarting"
mwl-confirm title="Warning!" message="Are you sure you want to stop connectivity to the application?"
on-confirm="stopApp(appSummary)" confirm-button-type="danger" cancel-button-type="default">
mwl-confirm title="Warning!" message="Are you sure you want to stop connectivity to the application?"
on-confirm="stopApp(appSummary)" confirm-button-type="danger"
cancel-button-type="default">
Stop
</button>
</div>
Expand Down Expand Up @@ -169,10 +171,26 @@ <h3 class="panel-title">{{service.entity.name}}</h3>
</div>
<div class="panel-body">
<button type="button" class="btn btn-xs btn-info" ng-disabled="disableServiceBinder"
ng-show="!service.boundService" ng-click="bindService(service)">Bind Service to App</button>
<button type="button" class="btn btn-xs btn-warning" ng-disabled="disableServiceBinder"
ng-show="service.boundService" ng-click="unbindService(service)">Unbind Service to App</button>
ng-show="!service.boundService" mwl-confirm title="Notice!" message="You will need to <b>restage</b> this application before this service is available."
on-confirm="bindService(service)" confirm-button-type="info" cancel-button-type="default">Bind Service</button>
<button type="button" class="btn btn-xs btn-danger" ng-disabled="disableServiceBinder"
ng-show="service.boundService" mwl-confirm title="Warning!" message="Are you sure you want to unbind this service?"
on-confirm="unbindService(service)" confirm-button-type="danger"
cancel-button-type="default">Unbind Service</button>
</div>
<div class="panel-heading" ng-show='service.credentials'>
<h3 class="panel-title">VCAP Info</h3>
</div>
<div class="panel-body" ng-show='service.credentials' ng-init='showCredentials=false'>
<button type="button" class="btn btn-xs btn-danger" ng-hide="showCredentials" mwl-confirm
title="Warning!" message="These are senstive data DO NOT SHARE!"
on-confirm="showCredentials=true" confirm-button-type="danger"
cancel-button-type="default">Show Credentials</button>
<button type="button" class="btn btn-xs btn-info" ng-show="showCredentials" ng-click="showCredentials=false">Hide Credentials</button>
<div ng-show='showCredentials'>{{service.credentials | json}}</div>

</div>

</div>
</div>
</div>
26 changes: 13 additions & 13 deletions static/app/views/partials/service_destroyer.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<div ng-switch="view.status">
<button type="button" class="btn btn-xs btn-primary" ng-click="view.showDestroyer('confirmed')"
ng-switch-when="unconfirmed">Delete Service Instance</button>
<div ng-switch-when="confirmed">
Delete Service?
<button type="button" class="btn btn-xs btn-danger" ng-click="view.deleteService(service)">Yes</button>
<button class="btn btn-xs btn-info" ng-click="view.showDestroyer('unconfirmed')">No</button>
</div>
<div ng-switch-when="error">
<span class="label label-danger">{{view.message}}</span>
</div>
<div ng-switch-when="success">
<span class="label label-success">{{view.message}}</span>
</div>
<button type="button" class="btn btn-xs btn-warning" mwl-confirm title="Warning!"
message="Are you sure you want to delete this service instance?" on-confirm="view.deleteService(service, false)"
confirm-button-type="danger" cancel-button-type="default" ng-switch-when="unconfirmed" ng-disabled='view.disableButton'>
Delete Service Instance
</button>
<button type="button" class="btn btn-xs btn-danger" mwl-confirm title="Warning!"
message="This service instance is bound to one or more apps!" on-confirm="view.deleteService(service, true)"
confirm-button-type="danger" cancel-button-type="default" ng-switch-when="boundError" ng-disabled='view.disableButton'>
Delete Bound Service Instance
</button>
<button type="button" class="btn btn-xs btn-info" ng-click="showTab('serviceInstances')" ng-switch-when="error" ng-disabled='view.disableButton'>
Unknown Error, Click to Refresh.
</button>
</div>
Loading