Add sign certificate action to cluster panel
This patch adds sign certificate action as item action to cluster table view and details view. Change-Id: I51636c377ecc105f5b290f7fb4e5c463cdc7d950 Implements: blueprint cluster-certificates
This commit is contained in:
parent
f07baab8e0
commit
c8d9a128a1
@ -126,8 +126,8 @@ class Clusters(generic.View):
|
|||||||
|
|
||||||
|
|
||||||
@urls.register
|
@urls.register
|
||||||
class Certificates(generic.View):
|
class Certificate(generic.View):
|
||||||
"""API for Magnum Certificates"""
|
"""API for retrieving a single certificate"""
|
||||||
url_regex = r'container_infra/certificates/(?P<cluster_id>[^/]+)$'
|
url_regex = r'container_infra/certificates/(?P<cluster_id>[^/]+)$'
|
||||||
|
|
||||||
@rest_utils.ajax()
|
@rest_utils.ajax()
|
||||||
@ -139,6 +139,12 @@ class Certificates(generic.View):
|
|||||||
ca = magnum.certificate_show(request, cluster_id)
|
ca = magnum.certificate_show(request, cluster_id)
|
||||||
return ca.to_dict()
|
return ca.to_dict()
|
||||||
|
|
||||||
|
|
||||||
|
@urls.register
|
||||||
|
class Certificates(generic.View):
|
||||||
|
"""API for Magnum Certificates"""
|
||||||
|
url_regex = r'container_infra/certificates/$'
|
||||||
|
|
||||||
@rest_utils.ajax(data_required=True)
|
@rest_utils.ajax(data_required=True)
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
"""Create a new Certificate.
|
"""Create a new Certificate.
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
'horizon.dashboard.container-infra.clusters.create.service',
|
'horizon.dashboard.container-infra.clusters.create.service',
|
||||||
'horizon.dashboard.container-infra.clusters.delete.service',
|
'horizon.dashboard.container-infra.clusters.delete.service',
|
||||||
'horizon.dashboard.container-infra.clusters.show-certificate.service',
|
'horizon.dashboard.container-infra.clusters.show-certificate.service',
|
||||||
|
'horizon.dashboard.container-infra.clusters.sign-certificate.service',
|
||||||
'horizon.dashboard.container-infra.clusters.resourceType',
|
'horizon.dashboard.container-infra.clusters.resourceType',
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -40,6 +41,7 @@
|
|||||||
createClusterService,
|
createClusterService,
|
||||||
deleteClusterService,
|
deleteClusterService,
|
||||||
showCertificateService,
|
showCertificateService,
|
||||||
|
signCertificateService,
|
||||||
resourceType)
|
resourceType)
|
||||||
{
|
{
|
||||||
var clusterResourceType = registry.getResourceType(resourceType);
|
var clusterResourceType = registry.getResourceType(resourceType);
|
||||||
@ -58,6 +60,13 @@
|
|||||||
template: {
|
template: {
|
||||||
text: gettext('Show Certificate')
|
text: gettext('Show Certificate')
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.append({
|
||||||
|
id: 'signCertificateAction',
|
||||||
|
service: signCertificateService,
|
||||||
|
template: {
|
||||||
|
text: gettext('Sign Certificate')
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
clusterResourceType.batchActions
|
clusterResourceType.batchActions
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc controller
|
||||||
|
* @name horizon.dashboard.container-infra.clusters.signCertificateController
|
||||||
|
* @ngController
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Controller for the container-infra cluster in sign certificate modal
|
||||||
|
*/
|
||||||
|
angular
|
||||||
|
.module('horizon.dashboard.container-infra.clusters')
|
||||||
|
.controller('horizon.dashboard.container-infra.clusters.signCertificateController', signCertificateController);
|
||||||
|
|
||||||
|
signCertificateController.$inject = [
|
||||||
|
'horizon.app.core.openstack-service-api.magnum',
|
||||||
|
'horizon.dashboard.container-infra.clusters.sign-certificate-model'
|
||||||
|
];
|
||||||
|
|
||||||
|
function signCertificateController(magnum, model) {
|
||||||
|
var ctrl = this;
|
||||||
|
ctrl.changeFile = changeFile;
|
||||||
|
ctrl.model = model;
|
||||||
|
ctrl.form = null;
|
||||||
|
magnum.getCluster(model.newCertificateSpec.cluster_uuid).success(onGetCluster);
|
||||||
|
|
||||||
|
function onGetCluster(response) {
|
||||||
|
ctrl.model.cluster_name = response.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeFile(files) {
|
||||||
|
// NOTE: this uses on-file-changed directive in Swift-UI included Horizon.
|
||||||
|
if (files.length) {
|
||||||
|
// load csr file and set into model
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.readAsText(files[0]);
|
||||||
|
reader.onload = function(ev){
|
||||||
|
model.newCertificateSpec.csr = reader.result;
|
||||||
|
ctrl.model.csrfile = files[0];
|
||||||
|
ctrl.form.$setDirty();
|
||||||
|
}
|
||||||
|
// Note that a $scope.$digest() is now needed for the change to the ngModel to be
|
||||||
|
// reflected in the page (since this callback is fired from inside a DOM event)
|
||||||
|
// but the on-file-changed directive currently does a digest after this callback
|
||||||
|
// is invoked.
|
||||||
|
} else {
|
||||||
|
model.newCertificateSpec.csr = "";
|
||||||
|
ctrl.model.csrfile = null;
|
||||||
|
ctrl.form.$setPristine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
@ -0,0 +1,39 @@
|
|||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" ng-click="$dismiss()" aria-hidden="true" aria-label="Close">
|
||||||
|
<span aria-hidden="true" class="fa fa-times"></span>
|
||||||
|
</button>
|
||||||
|
<div class="h3 modal-title">
|
||||||
|
<translate>Sign Certificate To Cluster: {$ ctrl.model.cluster_name $}</translate>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-form="ctrl.form">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label required" for="csr-file">
|
||||||
|
<translate>CSR File</translate>
|
||||||
|
<span class="hz-icon-required fa fa-asterisk"></span>
|
||||||
|
</label>
|
||||||
|
<input id="csr-file" type="file" name="file" required
|
||||||
|
ng-model="ctrl.model.csrfile" on-file-change="ctrl.changeFile">
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-default" ng-click="$dismiss()">
|
||||||
|
<span class="fa fa-close"></span>
|
||||||
|
<translate>Cancel</translate>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary" ng-click="$close(ctrl.model)"
|
||||||
|
ng-disabled="ctrl.form.$invalid">
|
||||||
|
<span class="fa fa-upload"></span>
|
||||||
|
<translate>Sign Certificate</translate>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('horizon.dashboard.container-infra.clusters')
|
||||||
|
.factory('horizon.dashboard.container-infra.clusters.sign-certificate-model', CertificateModel);
|
||||||
|
|
||||||
|
CertificateModel.$inject = [
|
||||||
|
'horizon.app.core.openstack-service-api.magnum'
|
||||||
|
];
|
||||||
|
|
||||||
|
function CertificateModel(magnum) {
|
||||||
|
var model = {
|
||||||
|
newClusterSpec: {},
|
||||||
|
cluster_name: "",
|
||||||
|
csrfile: null,
|
||||||
|
|
||||||
|
// API methods
|
||||||
|
init: init,
|
||||||
|
signCertificate: signCertificate
|
||||||
|
};
|
||||||
|
|
||||||
|
function init(cluster_id) {
|
||||||
|
// Reset the new Certificate spec
|
||||||
|
model.newCertificateSpec = {
|
||||||
|
cluster_uuid: cluster_id,
|
||||||
|
csr: ""
|
||||||
|
};
|
||||||
|
model.cluster_name = "";
|
||||||
|
model.csrfile = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function signCertificate() {
|
||||||
|
var finalSpec = angular.copy(model.newCertificateSpec);
|
||||||
|
|
||||||
|
cleanNullProperties(finalSpec);
|
||||||
|
|
||||||
|
return magnum.signCertificate(finalSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanNullProperties(finalSpec) {
|
||||||
|
// Initially clean fields that don't have any value.
|
||||||
|
for (var key in finalSpec) {
|
||||||
|
if (finalSpec.hasOwnProperty(key) && finalSpec[key] === null) {
|
||||||
|
delete finalSpec[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
})();
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('horizon.dashboard.container-infra.clusters')
|
||||||
|
.controller('horizon.dashboard.container-infra.clusters.sign-certificate-modal', SignCertificateModal);
|
||||||
|
|
||||||
|
SignCertificateModal.$inject = [
|
||||||
|
'$modal',
|
||||||
|
'horizon.app.core.workflow.factory',
|
||||||
|
'horizon.framework.util.i18n.gettext',
|
||||||
|
'horizon.framework.widgets.modal-wait-spinner.service',
|
||||||
|
'horizon.framework.widgets.toast.service',
|
||||||
|
'horizon.dashboard.container-infra.basePath'
|
||||||
|
];
|
||||||
|
|
||||||
|
function SignCertificateModal(modal, gettext, spinner, toast, basePath) {
|
||||||
|
var ctrl = this;
|
||||||
|
|
||||||
|
ctrl.model = {
|
||||||
|
cluster: model.cluster_id,
|
||||||
|
view_file: null, // file object managed by angular form ngModel
|
||||||
|
upload_file: null, // file object from the DOM element with the actual upload
|
||||||
|
DELIMETER: model.DELIMETER
|
||||||
|
};
|
||||||
|
ctrl.form = null; // set by the HTML
|
||||||
|
ctrl.changeFile = changeFile;
|
||||||
|
|
||||||
|
///////////
|
||||||
|
|
||||||
|
function changeFile(files) {
|
||||||
|
if (files.length) {
|
||||||
|
// update the upload file & its name
|
||||||
|
ctrl.model.upload_file = files[0];
|
||||||
|
ctrl.model.name = files[0].name;
|
||||||
|
ctrl.form.name.$setDirty();
|
||||||
|
|
||||||
|
// Note that a $scope.$digest() is now needed for the change to the ngModel to be
|
||||||
|
// reflected in the page (since this callback is fired from inside a DOM event)
|
||||||
|
// but the on-file-changed directive currently does a digest after this callback
|
||||||
|
// is invoked.
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
})();
|
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc overview
|
||||||
|
* @name horizon.dashboard.container-infra.clusters.sign-certificate.service
|
||||||
|
* @description Service for the container-infra cluster sign certificate modal
|
||||||
|
*/
|
||||||
|
angular
|
||||||
|
.module('horizon.dashboard.container-infra.clusters')
|
||||||
|
.factory('horizon.dashboard.container-infra.clusters.sign-certificate.service', signCertificateService);
|
||||||
|
|
||||||
|
signCertificateService.$inject = [
|
||||||
|
'$modal',
|
||||||
|
'horizon.app.core.openstack-service-api.magnum',
|
||||||
|
'horizon.framework.util.actions.action-result.service',
|
||||||
|
'horizon.framework.util.i18n.gettext',
|
||||||
|
'horizon.framework.util.q.extensions',
|
||||||
|
'horizon.framework.widgets.toast.service',
|
||||||
|
'horizon.dashboard.container-infra.clusters.basePath',
|
||||||
|
'horizon.dashboard.container-infra.clusters.resourceType',
|
||||||
|
'horizon.dashboard.container-infra.clusters.sign-certificate-model'
|
||||||
|
];
|
||||||
|
|
||||||
|
function signCertificateService(
|
||||||
|
$modal, magnum, actionResult, gettext, $qExtensions, toast, basePath, resourceType, model
|
||||||
|
) {
|
||||||
|
|
||||||
|
var message = {
|
||||||
|
success: gettext('Certificate %s was successfully signed.')
|
||||||
|
};
|
||||||
|
|
||||||
|
var service = {
|
||||||
|
initScope: initScope,
|
||||||
|
perform: perform,
|
||||||
|
allowed: allowed
|
||||||
|
};
|
||||||
|
|
||||||
|
return service;
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
function initScope($scope) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function signCertificateModal(html, $modal) {
|
||||||
|
var localSpec = {
|
||||||
|
backdrop: 'static',
|
||||||
|
controller: 'horizon.dashboard.container-infra.clusters.signCertificateController as ctrl',
|
||||||
|
templateUrl: html
|
||||||
|
};
|
||||||
|
return $modal.open(localSpec).result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function perform(selected) {
|
||||||
|
model.init(selected.id);
|
||||||
|
return signCertificateModal(basePath + 'sign-certificate/sign-certificate-modal.html', $modal)
|
||||||
|
.then(submit);
|
||||||
|
}
|
||||||
|
|
||||||
|
function allowed() {
|
||||||
|
return $qExtensions.booleanAsPromise(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit(){
|
||||||
|
return model.signCertificate().then(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
function success(response) {
|
||||||
|
magnum.downloadTextAsFile(response.data.pem, model.cluster_name + "_cert.pem");
|
||||||
|
|
||||||
|
response.data.id = response.data.uuid;
|
||||||
|
toast.add('success', interpolate(message.success, [response.data.id]));
|
||||||
|
var result = actionResult.getActionResult()
|
||||||
|
.created(resourceType, response.data.id);
|
||||||
|
return result.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
Loading…
x
Reference in New Issue
Block a user