Change cluster creating action for using json schema

This patch changes to define schema and form in json on controller.
Along with the change, the test file is also being modified.

Change-Id: I3a6d123c1249069417d4644d245ccee942dc4aeb
Implements: blueprint angular-json-schema
This commit is contained in:
Shu Muto 2017-01-23 18:45:41 +09:00
parent 2f01c46a40
commit 8ebe759e18
19 changed files with 447 additions and 586 deletions

View File

@ -1,74 +0,0 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* 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.model', ClusterModel);
ClusterModel.$inject = [
'horizon.app.core.openstack-service-api.magnum'
];
function ClusterModel(magnum) {
var model = {
newClusterSpec: {},
templateKeypair: null,
// API methods
init: init,
createCluster: createCluster
};
function initNewClusterSpec() {
model.newClusterSpec = {
name: null,
cluster_template_id: null,
master_count: null,
node_count: null,
discover_url: null,
create_timeout: null,
keypair: null
};
}
function init() {
// Reset the new Cluster spec
initNewClusterSpec();
}
function createCluster() {
var finalSpec = angular.copy(model.newClusterSpec);
cleanNullProperties(finalSpec);
return magnum.createCluster(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;
}
})();

View File

@ -1,60 +0,0 @@
/**
* (c) Copyright 2016 NEC Corporation
*
* 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';
describe('horizon.dashboard.container-infra.clusters.model', function() {
var model, specModel;
specModel = {
name: null,
cluster_template_id: null,
master_count: null,
node_count: null,
discover_url: null,
create_timeout: null,
keypair: null
};
beforeEach(module('horizon.dashboard.container-infra.clusters'));
beforeEach(inject(function($injector) {
model = $injector.get('horizon.dashboard.container-infra.clusters.model');
}));
it('newClusterSpec', testTemplateModel);
function testTemplateModel() {
model.init();
expect(specModel).toEqual(model.newClusterSpec);
}
it('createClusterTemplate', inject(function($q, $injector) {
var magnum = $injector.get('horizon.app.core.openstack-service-api.magnum');
var deferred = $q.defer();
spyOn(magnum, 'createCluster').and.returnValue(deferred.promise);
model.init();
model.createCluster();
expect(magnum.createCluster).toHaveBeenCalled();
model.newClusterSpec.name = 'notnull';
model.createCluster();
expect(magnum.createCluster).toHaveBeenCalled();
}));
});
})();

View File

@ -1,63 +0,0 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* 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.workflow', ClusterWorkflow);
ClusterWorkflow.$inject = [
'horizon.dashboard.container-infra.basePath',
'horizon.app.core.workflow.factory',
'horizon.framework.util.i18n.gettext'
];
function ClusterWorkflow(basePath, workflowService, gettext) {
return workflowService({
title: gettext('Create Cluster'),
steps: [
{
title: gettext('Info'),
templateUrl: basePath + 'clusters/create/info/info.html',
helpUrl: basePath + 'clusters/create/info/info.help.html',
formName: 'clusterInfoForm'
},
{
title: gettext('Size'),
templateUrl: basePath + 'clusters/create/size/size.html',
helpUrl: basePath + 'clusters/create/size/size.help.html',
formName: 'clusterSizeForm'
},
{
title: gettext('Misc'),
templateUrl: basePath + 'clusters/create/misc/misc.html',
helpUrl: basePath + 'clusters/create/misc/misc.help.html',
formName: 'clusterMiscForm'
}
],
btnText: {
finish: gettext('Create')
},
btnIcon: {
finish: 'fa fa-check'
}
});
}
})();

View File

@ -26,30 +26,28 @@
createService.$inject = [
'$location',
'horizon.app.core.openstack-service-api.magnum',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.util.actions.action-result.service',
'horizon.framework.util.i18n.gettext',
'horizon.framework.util.q.extensions',
'horizon.framework.widgets.modal.wizard-modal.service',
'horizon.framework.widgets.form.ModalFormService',
'horizon.framework.widgets.toast.service',
'horizon.dashboard.container-infra.clusters.model',
'horizon.dashboard.container-infra.clusters.events',
'horizon.dashboard.container-infra.clusters.resourceType',
'horizon.dashboard.container-infra.clusters.workflow'
];
function createService(
$location, policy, actionResult, gettext, $qExtensions, wizardModalService, toast,
model, events, resourceType, createWorkflow
$location, magnum, policy, actionResult, gettext, $qExtensions, modal, toast,
resourceType, workflow
) {
var scope;
var config;
var message = {
success: gettext('Cluster %s was successfully created.')
};
var service = {
initAction: initAction,
perform: perform,
allowed: allowed
};
@ -58,30 +56,33 @@
//////////////
function initAction() {
}
function perform(selected, $scope) {
scope = $scope;
scope.workflow = createWorkflow;
scope.model = model;
scope.$on('$destroy', function() {
});
scope.model.init();
scope.selected = selected;
return wizardModalService.modal({
scope: scope,
workflow: createWorkflow,
submit: submit
}).result;
config = workflow.init('create', gettext('Create'), $scope);
if (typeof selected !== 'undefined') {
config.model.cluster_template_id = selected.id;
}
return modal.open(config).then(submit);
}
function allowed() {
return $qExtensions.booleanAsPromise(true);
}
function submit() {
return model.createCluster().then(success);
function submit(context) {
context.model = cleanNullProperties(context.model);
return magnum.createCluster(context.model, false).then(success, true);
}
function cleanNullProperties(model) {
// Initially clean fields that don't have any value.
// Not only "null", blank too.
for (var key in model) {
if (model.hasOwnProperty(key) && model[key] === null || model[key] === "" ||
key === "tabs") {
delete model[key];
}
}
return model;
}
function success(response) {

View File

@ -19,13 +19,16 @@
describe('horizon.dashboard.container-infra.clusters.create.service', function() {
var service, $scope, $q, deferred, deferredModal, magnum;
var wizardModalService = {
modal: function (config) {
deferredModal = $q.defer();
deferredModal.resolve(config.scope.model);
return {result: deferredModal.promise};
var service, $scope, $q, deferred, magnum, workflow;
var model = {
id: 1
};
var modal = {
open: function(config) {
config.model = model;
deferred = $q.defer();
deferred.resolve(config);
return deferred.promise;
}
};
@ -36,7 +39,7 @@
beforeEach(module('horizon.dashboard.container-infra.clusters'));
beforeEach(module(function($provide) {
$provide.value('horizon.framework.widgets.modal.wizard-modal.service', wizardModalService);
$provide.value('horizon.framework.widgets.form.ModalFormService', modal);
}));
beforeEach(inject(function($injector, _$rootScope_, _$q_) {
@ -44,9 +47,12 @@
$scope = _$rootScope_.$new();
service = $injector.get('horizon.dashboard.container-infra.clusters.create.service');
magnum = $injector.get('horizon.app.core.openstack-service-api.magnum');
workflow = $injector.get('horizon.dashboard.container-infra.clusters.workflow');
deferred = $q.defer();
deferred.resolve({data: {uuid: 1}});
spyOn(magnum, 'createCluster').and.returnValue(deferred.promise);
spyOn(modal, 'open').and.callThrough();
spyOn(workflow, 'init').and.returnValue({model: model});
}));
it('should check the policy if the user is allowed to create cluster', function() {
@ -54,36 +60,15 @@
expect(allowed).toBeTruthy();
});
it('open the modal and should destroy event watchers', function() {
spyOn(wizardModalService, 'modal').and.callThrough();
service.initAction();
service.perform(null, $scope);
it('open the modal', inject(function($timeout) {
service.perform(model, $scope);
$scope.$emit('$destroy');
expect(modal.open).toHaveBeenCalled();
expect(wizardModalService.modal).toHaveBeenCalled();
var modalArgs = wizardModalService.modal.calls.argsFor(0)[0];
expect(modalArgs.scope).toEqual($scope);
expect(modalArgs.workflow).toBeDefined();
expect(modalArgs.submit).toBeDefined();
});
it('should submit create', inject(function($timeout) {
spyOn(wizardModalService, 'modal').and.callThrough();
service.initAction();
service.perform(null, $scope);
var modalArgs = wizardModalService.modal.calls.argsFor(0)[0];
modalArgs.submit();
$timeout.flush();
$scope.$apply();
expect(magnum.createCluster).toHaveBeenCalled();
}));
});
})();

View File

@ -1,86 +0,0 @@
/**
* Copyright 2015 NEC Corporation
*
* 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 createClusterInfoController
* @ngController
*
* @description
* Controller for the container-infra cluster info step in create workflow
*/
angular
.module('horizon.dashboard.container-infra.clusters')
.controller('createClusterInfoController', createClusterInfoController);
createClusterInfoController.$inject = [
'$q',
'$scope',
'horizon.dashboard.container-infra.basePath',
'horizon.app.core.openstack-service-api.magnum'
];
function createClusterInfoController($q, $scope, basePath, magnum) {
var ctrl = this;
ctrl.cluster_templates = [{id:"", name: gettext("Choose a Cluster Template")}];
$scope.model.newClusterSpec.cluster_template_id = "";
$scope.cluster_template_detail = {
name: "",
id: "",
coe: "",
image_id: "",
public: "",
registry_enabled: "",
tls_disabled: "",
apiserver_port: "",
keypair_id: ""
};
$scope.changeClusterTemplate = function() {
angular.forEach(ctrl.cluster_templates, function(template) {
if ($scope.model.newClusterSpec.cluster_template_id === template.id) {
$scope.cluster_template_detail.name = template.name;
$scope.cluster_template_detail.id = template.id;
$scope.cluster_template_detail.coe = template.coe;
$scope.cluster_template_detail.image_id = template.image_id;
$scope.cluster_template_detail.public = template.public;
$scope.cluster_template_detail.registry_enabled = template.registry_enabled;
$scope.cluster_template_detail.tls_disabled = template.tls_disabled;
$scope.cluster_template_detail.apiserver_port = template.apiserver_port;
$scope.cluster_template_detail.keypair = template.keypair_id;
$scope.model.templateKeypair = template.keypair_id;
}
});
};
init();
function init() {
magnum.getClusterTemplates({paginate: false}).success(onGetClusterTemplates);
}
function onGetClusterTemplates(response) {
Array.prototype.push.apply(ctrl.cluster_templates, response.items);
if ($scope.selected instanceof Object) {
$scope.model.newClusterSpec.cluster_template_id = $scope.selected.id;
$scope.changeClusterTemplate();
}
}
}
})();

View File

@ -1,52 +0,0 @@
<div ng-controller="createClusterInfoController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="cluster-name" translate>Cluster Name</label>
<input name="cluster-name" type="text" class="form-control" id="cluster-name"
ng-model="model.newClusterSpec.name"
placeholder="{$ 'Name of the cluster to create.'|translate $}">
</div>
<div class="form-group">
<label class="control-label" for="cluster-model">
<translate>Cluster Template</translate>
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<select class="form-control" name="cluster-model" id="cluster-model"
ng-model="model.newClusterSpec.cluster_template_id"
ng-required="true"
ng-options="cluster_template.id as cluster_template.name|noName for cluster_template in ctrl.cluster_templates"
ng-change="changeClusterTemplate()">
</select>
</div>
<div class="detail" ng-show="model.newClusterSpec.cluster_template_id">
<span translate class="h4">Cluster Template Detail</span>
<dl class="dl-horizontal">
<dt translate>Name</dt>
<dd><a ng-href="project/ngdetails/OS::Magnum::ClusterTemplate/{$ cluster_template_detail.id $}" ng-click="cancel()">
{$ cluster_template_detail.name|noName $}
</a></dd>
<dt translate>ID</dt>
<dd>{$ cluster_template_detail.id $}</dd>
<dt translate>COE</dt>
<dd>{$ cluster_template_detail.coe $}</dd>
<dt translate>Image ID</dt>
<dd>{$ cluster_template_detail.image_id $}</dd>
<dt translate>Keypair</dt>
<dd>{$ cluster_template_detail.keypair|noValue $}</dd>
<dt translate>Public</dt>
<dd>{$ cluster_template_detail.public $}</dd>
<dt translate>Registry Enabled</dt>
<dd>{$ cluster_template_detail.registry_enabled $}</dd>
<dt translate>TLS Disabled</dt>
<dd>{$ cluster_template_detail.tls_disabled $}</dd>
<dt translate>API Server Port</dt>
<dd>{$ cluster_template_detail.apiserver_port|noValue $}</dd>
</dl>
</div>
</div>
</div>
</div>

View File

@ -1,66 +0,0 @@
/**
* Copyright 2015 NEC Corporation
*
* 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 createClusterMiscController
* @ngController
*
* @description
* Controller for the container-infra cluster misc step in create workflow
*/
angular
.module('horizon.dashboard.container-infra.clusters')
.controller('createClusterMiscController', createClusterMiscController);
createClusterMiscController.$inject = [
'$scope',
'horizon.app.core.openstack-service-api.nova'
];
function createClusterMiscController($scope, nova) {
var ctrl = this;
ctrl.keypairs = [{id:null, name: gettext("Choose a Keypair")}];
$scope.model.newClusterSpec.keypair = null;
init();
function init() {
nova.getKeypairs().success(onGetKeypairs);
}
function onGetKeypairs(response) {
angular.forEach(response.items, function(item) {
ctrl.keypairs.push({id: item.keypair.name, name: item.keypair.name});
});
}
function getKeypair() {
return $scope.model.templateKeypair;
}
function toggleKeypairRequirement(newValue) {
ctrl.templateKeypair = newValue;
}
var keypairWatcher = $scope.$watch(getKeypair, toggleKeypairRequirement, true);
$scope.$on('$destroy', function() {
keypairWatcher();
});
}
})();

View File

@ -1,28 +0,0 @@
<div ng-controller="createClusterMiscController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="cluster-discovery-url" translate>Discovery URL</label>
<input name="cluster-discovery-url" type="text" class="form-control"
ng-model="model.newClusterSpec.discovery_url" id="cluster-discovery-url"
placeholder="{$ 'Specifies custom discovery url for node discovery.'|translate $}">
</div>
<div class="form-group">
<label class="control-label" for="cluster-timeout" translate>Timeout</label>
<input name="cluster-timeout" type="number" min="0" class="form-control"
ng-model="model.newClusterSpec.create_timeout" id="cluster-timeout"
placeholder="{$ 'The timeout for cluster creation in minutes. Set to 0 for no timeout. The default is no timeout.'|translate $}">
</div>
<div class="form-group">
<label class="control-label" for="cluster-keypair">
<translate>Keypair</translate>
<span class="hz-icon-required fa fa-asterisk" ng-if="ctrl.templateKeypair === null"></span>
</label>
<select name="cluster-keypair" type="text" class="form-control" id="cluster-keypair"
ng-model="model.newClusterSpec.keypair" ng-required="ctrl.templateKeypair === null"
ng-options="keypair.id as keypair.name for keypair in ctrl.keypairs">
</select>
</div>
</div>
</div>
</div>

View File

@ -1,38 +0,0 @@
/**
* Copyright 2015 NEC Corporation
*
* 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 createClusterSizeController
* @ngController
*
* @description
* Controller for the container-infra cluster size step in create workflow
*/
angular
.module('horizon.dashboard.container-infra.clusters')
.controller('createClusterSizeController', createClusterSizeController);
createClusterSizeController.$inject = [
];
function createClusterSizeController() {
}
})();

View File

@ -1,20 +0,0 @@
<div ng-controller="createClusterSizeController as ctrl">
<div class="row">
<div class="col-xs-12 col-sm-6">
<div class="form-group">
<label class="control-label" for="cluster-master-count" translate>Master Count</label>
<input name="cluster-master-count" type="number" min="1" id="cluster-master-count"
class="form-control" ng-model="model.newClusterSpec.master_count"
placeholder="{$ 'The number of master nodes for the cluster.'|translate $}">
</div>
</div>
<div class="col-xs-12 col-sm-6">
<div class="form-group">
<label class="control-label" for="cluster-node-count" translate>Node Count</label>
<input name="cluster-node-count" type="number" min="1" id="cluster-node-count"
class="form-control" ng-model="model.newClusterSpec.node_count"
placeholder="{$ 'The cluster node count.'|translate $}">
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,88 @@
/**
* 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 clusterTemplateController
* @ngController
*
* @description
* Controller to show cluster template info for info step in workflow
*/
angular
.module('horizon.dashboard.container-infra.clusters')
.controller(
'horizon.dashboard.container-infra.clusters.workflow.clusterTemplateController',
clusterTemplateController);
clusterTemplateController.$inject = [
'$scope',
'horizon.app.core.openstack-service-api.magnum'
];
function clusterTemplateController($scope, magnum) {
var ctrl = this;
init();
function init() {
ctrl.clusterTemplate = {
name: "",
id: "",
coe: "",
image_id: "",
public: "",
registry_enabled: "",
tls_disabled: "",
apiserver_port: "",
keypair_id: ""
};
}
loadClusterTemplate($scope.model.cluster_template_id);
function loadClusterTemplate(id, old) {
if (id !== old) {
if (id === '') {
$scope.model.keypair = "";
} else {
magnum.getClusterTemplate(id).then(onGetClusterTemplate);
}
}
}
function onGetClusterTemplate(response) {
ctrl.clusterTemplate = response.data;
if (response.data.keypair_id === null) {
$scope.model.keypair = "";
} else {
$scope.model.keypair = response.data.keypair_id;
}
}
function watchClusterTemplateId() {
return $scope.model.cluster_template_id;
}
var clusterTemplateWatcher = $scope.$watch(
watchClusterTemplateId, loadClusterTemplate, true
);
$scope.$on('$destroy', function() {
clusterTemplateWatcher();
});
}
})();

View File

@ -1,6 +1,4 @@
/**
* (c) Copyright 2016 NEC Corporation
*
* 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
@ -17,62 +15,46 @@
(function() {
'use strict';
describe('horizon.dashboard.container-infra.clusters', function() {
var magnum, controller, $scope;
function fakePromise() {
return {
success : angular.noop,
items : {
id : ''
}
};
}
$scope = {
model: {
newClusterSpec: {
id: ''
}
}
};
var magnum, controller, $scope, $q, deferred;
beforeEach(module('horizon.framework'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.container-infra.clusters'));
beforeEach(inject(function ($injector) {
beforeEach(inject(function ($injector, _$rootScope_, _$q_) {
$q = _$q_;
$scope = _$rootScope_.$new();
$scope.model = {
cluster_template_id: '1'
};
magnum = $injector.get('horizon.app.core.openstack-service-api.magnum');
controller = $injector.get('$controller');
spyOn(magnum, 'getClusterTemplates').and.callFake(fakePromise);
deferred = $q.defer();
deferred.resolve({data: {keypair_id: '1'}});
spyOn(magnum, 'getClusterTemplate').and.returnValue(deferred.promise);
createController($scope);
}));
function createController($scoped) {
return controller('createClusterInfoController', {
$scope: $scoped,
magnum: magnum
});
return controller(
'horizon.dashboard.container-infra.clusters.workflow.clusterTemplateController',
{
$scope: $scoped,
magnum: magnum
});
}
it('should init() pass', function() {
createController($scope);
expect(magnum.getClusterTemplates).toHaveBeenCalled();
it('should load cluster template', function() {
expect(magnum.getClusterTemplate).toHaveBeenCalled();
});
it('should changeClusterTemplate() pass', function() {
createController($scope);
$scope.model.newClusterSpec.cluster_template_id = '1';
$scope.changeClusterTemplate();
expect($scope.cluster_template_detail.name).toBe('');
$scope.model.newClusterSpec.cluster_template_id = '';
$scope.changeClusterTemplate();
expect($scope.cluster_template_detail.name).toBe('Choose a Cluster Template');
it('should keypair is changed by cluster template\'s keypair', function() {
$scope.$apply();
expect($scope.model.keypair).toBe('1');
$scope.model.cluster_template_id = '';
$scope.$digest();
expect($scope.model.keypair).toBe('');
});
});
})();

View File

@ -0,0 +1,27 @@
<div ng-controller="horizon.dashboard.container-infra.clusters.workflow.clusterTemplateController as ctrl">
<div class="detail" ng-show="ctrl.clusterTemplate.id">
<span translate class="h4">Cluster Template Detail</span>
<dl class="dl-horizontal">
<dt translate>Name</dt>
<dd><a ng-href="project/ngdetails/OS::Magnum::ClusterTemplate/{$ ctrl.clusterTemplate.id $}" ng-click="cancel()">
{$ ctrl.clusterTemplate.name|noName $}
</a></dd>
<dt translate>ID</dt>
<dd>{$ ctrl.clusterTemplate.id $}</dd>
<dt translate>COE</dt>
<dd>{$ ctrl.clusterTemplate.coe $}</dd>
<dt translate>Image ID</dt>
<dd>{$ ctrl.clusterTemplate.image_id $}</dd>
<dt translate>Keypair</dt>
<dd>{$ ctrl.clusterTemplate.keypair_id|noValue $}</dd>
<dt translate>Public</dt>
<dd>{$ ctrl.clusterTemplate.public $}</dd>
<dt translate>Registry Enabled</dt>
<dd>{$ ctrl.clusterTemplate.registry_enabled $}</dd>
<dt translate>TLS Disabled</dt>
<dd>{$ ctrl.clusterTemplate.tls_disabled $}</dd>
<dt translate>API Server Port</dt>
<dd>{$ ctrl.clusterTemplate.apiserver_port|noValue $}</dd>
</dl>
</div>
</div>

View File

@ -0,0 +1,211 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* 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.workflow',
ClusterWorkflow);
ClusterWorkflow.$inject = [
'horizon.dashboard.container-infra.basePath',
'horizon.app.core.workflow.factory',
'horizon.framework.util.i18n.gettext',
'horizon.app.core.openstack-service-api.magnum',
'horizon.app.core.openstack-service-api.nova'
];
function ClusterWorkflow(basePath, workflowService, gettext, magnum, nova) {
var workflow = {
init: init
};
function init(action, title, $scope) {
var schema, form, model;
var clusterTemplates = [{value:"", name: gettext("Choose a Cluster Template")}];
var keypairs = [{value:"", name: gettext("Choose a Keypair")}];
// schema
schema = {
type: 'object',
properties: {
'name': {
title: gettext('Cluster Name'),
type: 'string'
},
'cluster_template_id': {
title: gettext('Cluster Template'),
type: 'string'
},
'master_count': {
title: gettext('Master Count'),
type: 'number',
minimum: 1
},
'node_count': {
title: gettext('Node Count'),
type: 'number',
minimum: 1
},
'discovery_url': {
title: gettext('Discovery URL'),
type: 'string'
},
'create_timeout': {
title: gettext('Timeout'),
type: 'number',
minimum: 0
},
'keypair': {
title: gettext('Keypair'),
type: 'string'
}
}
};
// form
form = [
{
type:'tabs',
tabs: [
{
title: gettext('Info'),
help: basePath + 'clusters/workflow/info.help.html',
type: 'section',
htmlClass: 'row',
items: [
{
type: 'section',
htmlClass: 'col-xs-12',
items: [
{
key: 'name',
placeholder: gettext('Name of the cluster.')
},
{
key: 'cluster_template_id',
type: 'select',
titleMap: clusterTemplates,
required: true
},
{
type: 'template',
templateUrl: basePath + 'clusters/workflow/cluster-template.html'
}
]
}
]
},
{
title: gettext('Size'),
help: basePath + 'clusters/workflow/size.help.html',
type: 'section',
htmlClass: 'row',
items: [
{
type: 'section',
htmlClass: 'col-xs-12',
items: [
{
key: 'master_count',
placeholder: gettext('The number of master nodes for the cluster.')
},
{
key: 'node_count',
placeholder: gettext('The cluster node count.')
}
]
}
]
},
{
title: gettext('Misc'),
help: basePath + 'clusters/workflow/misc.help.html',
type: 'section',
htmlClass: 'row',
items: [
{
type: 'section',
htmlClass: 'col-xs-12',
items: [
{
key: 'discovery_url',
placeholder: gettext('Specifies custom discovery url for node discovery.')
},
{
key: 'create_timeout',
/* eslint-disable max-len */
placeholder: gettext('The timeout for cluster creation in minutes.'),
description: gettext('Set to 0 for no timeout. The default is no timeout.')
},
{
key: 'keypair',
type: 'select',
titleMap: keypairs,
required: true
}
]
}
]
}
]
}
];
magnum.getClusterTemplates().then(onGetClusterTemplates);
nova.getKeypairs().then(onGetKeypairs);
function onGetKeypairs(response) {
angular.forEach(response.data.items, function(item) {
keypairs.push({value: item.keypair.name, name: item.keypair.name});
});
}
function onGetClusterTemplates(response) {
angular.forEach(response.data.items, function(item) {
clusterTemplates.push({value: item.id, name: item.name});
});
}
model = {
name: "",
cluster_template_id: "",
master_count: null,
node_count: null,
discovery_url: "",
create_timeout: null,
keypair: ""
};
var config = {
title: title,
schema: schema,
form: form,
model: model
};
$scope.model = model;
return config;
}
return workflow;
}
})();

View File

@ -0,0 +1,54 @@
/**
* (c) Copyright 2016 NEC Corporation
*
* 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';
describe('horizon.dashboard.container-infra.clusters.workflow', function() {
var workflow, magnum, nova, $scope, $q, deferred, keyDeferred;
beforeEach(module('horizon.app.core'));
beforeEach(module('horizon.framework'));
beforeEach(module('horizon.dashboard.container-infra.clusters'));
beforeEach(inject(function($injector, _$rootScope_, _$q_) {
$q = _$q_;
$scope = _$rootScope_.$new();
workflow = $injector.get(
'horizon.dashboard.container-infra.clusters.workflow');
magnum = $injector.get('horizon.app.core.openstack-service-api.magnum');
nova = $injector.get('horizon.app.core.openstack-service-api.nova');
deferred = $q.defer();
deferred.resolve({data:{items:{1:{name:1},2:{name:2}}}});
keyDeferred = $q.defer();
keyDeferred.resolve({data:{items:{1:{keypair:{name:1}},2:{keypair:{name:2}}}}});
spyOn(magnum, 'getClusterTemplates').and.returnValue(deferred.promise);
spyOn(nova, 'getKeypairs').and.returnValue(keyDeferred.promise);
}));
it('should be init', inject(function($timeout) {
var config = workflow.init('create', 'Create Cluster', $scope);
$timeout.flush();
expect(config.title).toBeDefined();
expect(config.schema).toBeDefined();
expect(config.form).toBeDefined();
expect(config.model).toBeDefined();
}));
});
})();