Merge "Drop the usage of nova extensions in JavaScript code"

This commit is contained in:
Zuul 2020-11-18 13:33:11 +00:00 committed by Gerrit Code Review
commit 6b702f4a1c
14 changed files with 26 additions and 437 deletions

View File

@ -11,29 +11,25 @@
rows=8>
</load-edit>
<div hz-if-nova-extensions='["DiskConfig"]'>
<div class="form-group">
<label for="disk-partition" translate>
Disk Partition
</label>
<select class="form-control"
id="disk-partition"
ng-model="model.newInstanceSpec.disk_config"
ng-options="option.value as option.text for option in ctrl.diskConfigOptions">
</select>
</div>
<div class="form-group">
<label for="disk-partition" translate>
Disk Partition
</label>
<select class="form-control"
id="disk-partition"
ng-model="model.newInstanceSpec.disk_config"
ng-options="option.value as option.text for option in ctrl.diskConfigOptions">
</select>
</div>
<div hz-if-nova-extensions='["ConfigDrive"]'>
<div class="form-group">
<div class="themable-checkbox">
<input type="checkbox"
id="config-drive"
ng-model="model.newInstanceSpec.config_drive">
<label for="config-drive">
<span translate>Configuration Drive</span>
</label>
</div>
<div class="form-group">
<div class="themable-checkbox">
<input type="checkbox"
id="config-drive"
ng-model="model.newInstanceSpec.config_drive">
<label for="config-drive">
<span translate>Configuration Drive</span>
</label>
</div>
</div>
</div>

View File

@ -37,7 +37,6 @@
'horizon.app.core.openstack-service-api.glance',
'horizon.app.core.openstack-service-api.neutron',
'horizon.app.core.openstack-service-api.nova',
'horizon.app.core.openstack-service-api.novaExtensions',
'horizon.app.core.openstack-service-api.security-group',
'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.app.core.openstack-service-api.settings',
@ -57,7 +56,6 @@
* @param {Object} glanceAPI
* @param {Object} neutronAPI
* @param {Object} novaAPI
* @param {Object} novaExtensions
* @param {Object} securityGroup
* @param {Object} serviceCatalog
* @param {Object} settings
@ -81,7 +79,6 @@
glanceAPI,
neutronAPI,
novaAPI,
novaExtensions,
securityGroup,
serviceCatalog,
settings,
@ -589,9 +586,7 @@
}
function onVolumeServiceEnabled() {
model.volumeBootable = true;
novaExtensions
.ifNameEnabled('BlockDeviceMappingV2Boot')
.then(onBootToVolumeSupported);
model.allowCreateVolumeFromImage = true;
if (!config || !config.disable_volume) {
getVolumes().then(resolveVolumes, failVolumes);
getAbsoluteLimits().then(resolveAbsoluteLimitsDeferred, resolveAbsoluteLimitsDeferred);
@ -605,9 +600,6 @@
resolveVolumeSnapshots();
}
}
function onBootToVolumeSupported() {
model.allowCreateVolumeFromImage = true;
}
function getVolumes() {
return cinderAPI.getVolumes({status: 'available', bootable: 1})
.then(onGetVolumes);

View File

@ -22,7 +22,6 @@
var model, scope, settings, $q, glance, IMAGE, VOLUME, VOLUME_SNAPSHOT, INSTANCE_SNAPSHOT;
var cinderEnabled = false;
var neutronEnabled = false;
var novaExtensionsEnabled = false;
var ifAllowedResolve = true;
var novaApi = {
@ -252,20 +251,6 @@
}
});
$provide.value('horizon.app.core.openstack-service-api.novaExtensions', {
ifNameEnabled: function() {
var deferred = $q.defer();
if (novaExtensionsEnabled) {
deferred.resolve();
} else {
deferred.reject();
}
return deferred.promise;
}
});
$provide.value('horizon.app.core.openstack-service-api.settings', {
getSetting: function(setting) {
var deferred = $q.defer();
@ -465,15 +450,6 @@
expect(model.volumeSnapshots.length).toBe(2);
});
it('should disable create volume from image if nova extensions disabled', function() {
cinderEnabled = true;
novaExtensionsEnabled = false;
model.initialize(true);
scope.$apply();
expect(model.allowCreateVolumeFromImage).toBe(false);
});
it('should default config_drive to false', function() {
model.initialize(true);
scope.$apply();

View File

@ -81,8 +81,7 @@
title: gettext('Key Pair'),
templateUrl: basePath + 'keypair/keypair.html',
helpUrl: basePath + 'keypair/keypair.help.html',
formName: 'launchInstanceKeypairForm',
novaExtension: 'Keypairs'
formName: 'launchInstanceKeypairForm'
},
{
id: 'configuration',
@ -97,8 +96,7 @@
templateUrl: basePath + 'server-groups/server-groups.html',
helpUrl: basePath + 'server-groups/server-groups.help.html',
formName: 'launchInstanceServerGroupsForm',
policy: stepPolicy.serverGroups,
novaExtension: 'ServerGroups'
policy: stepPolicy.serverGroups
},
{
id: 'hints',
@ -107,8 +105,7 @@
helpUrl: basePath + 'scheduler-hints/scheduler-hints.help.html',
formName: 'launchInstanceSchedulerHintsForm',
policy: stepPolicy.schedulerHints,
setting: 'LAUNCH_INSTANCE_DEFAULTS.enable_scheduler_hints',
novaExtension: 'SchedulerHints'
setting: 'LAUNCH_INSTANCE_DEFAULTS.enable_scheduler_hints'
},
{
id: 'metadata',

View File

@ -71,26 +71,14 @@
expect(launchInstanceWorkflow.steps[4].requiredServiceTypes).toEqual(['network']);
});
it('has a nova extension the key pair step depends on', function() {
expect(launchInstanceWorkflow.steps[6].novaExtension).toEqual("Keypairs");
});
it('has a policy rule for the server groups step', function() {
expect(launchInstanceWorkflow.steps[8].policy).toEqual(stepPolicy.serverGroups);
});
it('has a nova extension the server groups step depends on', function() {
expect(launchInstanceWorkflow.steps[8].novaExtension).toEqual("ServerGroups");
});
it('has a policy rule for the scheduler hints step', function() {
expect(launchInstanceWorkflow.steps[9].policy).toEqual(stepPolicy.schedulerHints);
});
it('has a nova extension the scheduler hints step depends on', function() {
expect(launchInstanceWorkflow.steps[9].novaExtension).toEqual("SchedulerHints");
});
});
})();

View File

@ -1,76 +0,0 @@
/*
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
*
* 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.app.core.cloud-services')
.directive('hzIfNovaExtensions', hzNovaExtensions);
hzNovaExtensions.$inject = [
'hzPromiseToggleTemplateDirective',
'horizon.app.core.openstack-service-api.novaExtensions'
];
/**
* @ngdoc directive
* @name hz.api:directive:hzIfNovaExtensions
* @module hz.api
* @description
*
* Add this directive to any element containing content which should
* only be evaluated when the specified nova extensions are enabled by
* the nova servers in the currently selected region. If the nova extensions
* are enabled, the content will be evaluated. Otherwise, the content will
* not be compiled. In addition, the element and everything contained by
* it will be removed completely, leaving a simple HTML comment.
*
* This is evaluated once per page load. In current horizon, this means
* it will get re-evaluated with events like the user opening another panel,
* changing logins, or changing their region.
*
* The hz-if-nova-extensions attribute may be set to a single extension (String)
* or an array of extensions (each one being a String).
* All of the following are examples:
*
* hz-if-nova-extensions='"ConfigDrive"'
* hz-if-nova-extensions='["ConfigDrive"]'
* hz-if-nova-extensions='["ConfigDrive", "DiskConfig"]'
*
* @example
*
* In the below, if the ConfigDrive nova extension is not enabled, then
* the div element with hz-if-nova-extensions and all of the elements inside
* of it will be removed and never evaluated by the angular compiler.
*
```html
<div hz-if-nova-extensions='"ConfigDrive"'>
<!-- ui code here -->
</div>
```
*/
function hzNovaExtensions(hzPromiseToggleTemplateDirective, novaExtensions) {
return angular.extend(
hzPromiseToggleTemplateDirective[0],
{
singlePromiseResolver: novaExtensions.ifNameEnabled,
name: 'hzIfNovaExtensions'
}
);
}
})();

View File

@ -1,89 +0,0 @@
/*
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
* Copyright 2015 ThoughtWorks 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';
describe('horizon.app.core.cloud-services.hzNovaExtension', function () {
var $compile, $scope, deferred, novaExtensionsAPI;
var template = [
'<div>',
'<div hz-if-nova-extensions=\'\"ext_name\"\'>',
'<div class="child-element">',
'</div>',
'</div>',
'</div>'
].join('');
beforeEach(function() {
novaExtensionsAPI = {
ifNameEnabled: function() {
return deferred.promise;
}
};
spyOn(novaExtensionsAPI, 'ifNameEnabled').and.callThrough();
module('horizon.app.core.cloud-services');
module('horizon.framework.util.promise-toggle');
module('horizon.app.core.openstack-service-api', function($provide) {
$provide.value(
'horizon.app.core.openstack-service-api.novaExtensions', novaExtensionsAPI
);
});
inject(function (_$compile_, _$q_, _$rootScope_) {
$compile = _$compile_;
deferred = _$q_.defer();
$scope = _$rootScope_.$new();
});
});
// Please note, this code is primarily intended to verify that the
// directive specifies the correct name and that it uses the settings
// service API. Testing of the variations on inputs being resolved
// are tested in the hz-promise-toggle spec.
it('should evaluate child elements when extension is enabled', function () {
var element = $compile(template)($scope);
deferred.resolve();
expect(element.children().length).toBe(0);
expect(novaExtensionsAPI.ifNameEnabled).toHaveBeenCalledWith('ext_name');
$scope.$apply();
expect(element.children().length).toBe(1);
});
it('should not evaluate child elements when extension is NOT enabled', function () {
var element = $compile(template)($scope);
deferred.reject();
expect(element.children().length).toBe(0);
expect(novaExtensionsAPI.ifNameEnabled).toHaveBeenCalledWith('ext_name');
$scope.$apply();
expect(element.children().length).toBe(0);
});
});
})();

View File

@ -17,7 +17,7 @@
(function() {
'use strict';
describe("novaExtensions", function() {
describe("extensions", function() {
var q = {
defer: function() {
return {

View File

@ -1,55 +0,0 @@
/**
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
*
* 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.app.core.openstack-service-api')
.factory('horizon.app.core.openstack-service-api.novaExtensions', novaExtensionsAPI);
novaExtensionsAPI.$inject = [
'$cacheFactory',
'horizon.app.core.openstack-service-api.extensions',
'horizon.app.core.openstack-service-api.nova'
];
/**
* @ngdoc service
* @name novaExtensionsAPI
* @param {Object} $cacheFactory
* @param {Object} extensionsAPI
* @param {Object} novaAPI
* @description
* Provides cached access to Nova Extensions with utilities to help
* with asynchronous data loading. The cache may be reset at any time
* by accessing the cache and calling removeAll. The next call to any
* function will retrieve fresh results.
*
* The enabled extensions do not change often, so using cached data will
* speed up results. Even on a local devstack in informal testing,
* this saved between 30 - 100 ms per request.
* @returns {Object} The service
*/
function novaExtensionsAPI($cacheFactory, extensionsAPI, novaAPI) {
return extensionsAPI({
cacheFactory: $cacheFactory(
'horizon.app.core.openstack-service-api.novaExtensions',
{capacity: 1}
),
serviceAPI: novaAPI
});
}
}());

View File

@ -1,91 +0,0 @@
/*
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
*
* 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("novaExtensions", function() {
var factory, q, novaAPI;
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module(function($provide) {
novaAPI = {getExtensions: function() {
return {then: angular.noop};
}};
q = {defer: function() {
return {resolve: angular.noop};
}};
$provide.value('$cacheFactory', function() {
return "cache";
});
$provide.value('$q', q);
$provide.value('horizon.app.core.openstack-service-api.nova', novaAPI);
}));
beforeEach(inject(function($injector) {
factory = $injector.get('horizon.app.core.openstack-service-api.novaExtensions');
}));
it("is defined", function() {
expect(factory).toBeDefined();
});
it("defines .cache", function() {
expect(factory.cache).toBeDefined();
});
it("defines .get", function() {
expect(factory.get).toBeDefined();
var postAction = {then: angular.noop};
spyOn(novaAPI, 'getExtensions').and.returnValue(postAction);
spyOn(postAction, 'then');
factory.get();
expect(novaAPI.getExtensions).toHaveBeenCalledWith({cache: factory.cache});
expect(postAction.then).toHaveBeenCalled();
var func = postAction.then.calls.argsFor(0)[0];
var testData = {data: {items: [1, 2, 3]}};
expect(func(testData)).toEqual([1, 2, 3]);
});
it("defines .ifNameEnabled", function() {
expect(factory.ifNameEnabled).toBeDefined();
var postAction = {then: angular.noop};
var deferred = {reject: angular.noop, resolve: angular.noop};
spyOn(q, 'defer').and.returnValue(deferred);
spyOn(factory, 'get').and.returnValue(postAction);
spyOn(postAction, 'then');
factory.ifNameEnabled("desired");
expect(factory.get).toHaveBeenCalled();
var func1 = postAction.then.calls.argsFor(0)[0];
var func2 = postAction.then.calls.argsFor(0)[1];
spyOn(deferred, 'reject');
func1();
expect(deferred.reject).toHaveBeenCalled();
spyOn(deferred, 'resolve');
var extensions = [{name: "desired"}];
func1(extensions);
expect(deferred.resolve).toHaveBeenCalled();
deferred.reject.calls.reset();
func2();
expect(deferred.reject).toHaveBeenCalledWith('Cannot get the extension list.');
});
});
})();

View File

@ -65,7 +65,6 @@
hardRebootServer: hardRebootServer,
startServer: startServer,
stopServer: stopServer,
getExtensions: getExtensions,
getFlavors: getFlavors,
getFlavor: getFlavor,
getFlavorExtraSpecs: getFlavorExtraSpecs,
@ -534,33 +533,6 @@
gettext('Unable to stop the server with id: %(id)s'));
}
/**
* @name getExtensions
* @param {Object} config - A configuration object
* @description
* Returns a list of enabled extensions.
*
* The listing result is an object with property "items". Each item is
* an extension.
* @example
* The following is an example response:
*
* {
* "items": [
* {
* "name": "Multinic"
* }
* ]
* }
* @returns {Object} The list of enable extensions
*/
function getExtensions(config) {
return apiService.get('/api/nova/extensions/', config)
.error(function () {
toastService.add('error', gettext('Unable to retrieve the extensions.'));
});
}
/**
* @name getFlavors
* @description

View File

@ -328,16 +328,6 @@
"error": "Unable to delete the server group with id 1",
"testInput": [1]
},
{
"func": "getExtensions",
"method": "get",
"path": "/api/nova/extensions/",
"data": "config",
"error": "Unable to retrieve the extensions.",
"testInput": [
"config"
]
},
{
"func": "getFlavors",
"method": "get",

View File

@ -50,13 +50,12 @@
'$q',
'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.app.core.openstack-service-api.policy',
'horizon.app.core.openstack-service-api.settings',
'horizon.app.core.openstack-service-api.novaExtensions'
'horizon.app.core.openstack-service-api.settings'
];
/////////////
function dashboardWorkflowDecorator($q, serviceCatalog, policy, settings, novaExtensions) {
function dashboardWorkflowDecorator($q, serviceCatalog, policy, settings) {
return decorator;
function decorator(spec) {
@ -82,9 +81,6 @@
if (step.setting) {
promises.push(settings.ifEnabled(step.setting, true, true));
}
if (step.novaExtension) {
promises.push(novaExtensions.ifNameEnabled(step.novaExtension));
}
if (promises.length > 0) {
step.checkReadiness = function () {
return $q.all(promises).then(function() {

View File

@ -17,14 +17,12 @@
'use strict';
describe('Workflow Decorator', function () {
var decoratorService, catalogService, policyService, settingsService, $scope, deferred,
novaExtensionsService;
var decoratorService, catalogService, policyService, settingsService, $scope, deferred;
var steps = [
{ id: '1' },
{ id: '2', requiredServiceTypes: ['foo-service'] },
{ id: '3', policy: 'foo-policy' },
{ id: '4', setting: 'STEPS.step_4_enabled' },
{ id: '5', novaExtension: 'foo-novaExtension'}
{ id: '4', setting: 'STEPS.step_4_enabled' }
];
var spec = { steps: steps };
@ -40,12 +38,9 @@
catalogService = $injector.get('horizon.app.core.openstack-service-api.serviceCatalog');
policyService = $injector.get('horizon.app.core.openstack-service-api.policy');
settingsService = $injector.get('horizon.app.core.openstack-service-api.settings');
novaExtensionsService = $injector
.get('horizon.app.core.openstack-service-api.novaExtensions');
spyOn(catalogService, 'ifTypeEnabled').and.returnValue(deferred.promise);
spyOn(policyService, 'ifAllowed').and.returnValue(deferred.promise);
spyOn(settingsService, 'ifEnabled').and.returnValue(deferred.promise);
spyOn(novaExtensionsService, 'ifNameEnabled').and.returnValue(deferred.promise);
}));
it('is a function', function() {
@ -63,8 +58,6 @@
expect(policyService.ifAllowed).toHaveBeenCalledWith('foo-policy');
expect(settingsService.ifEnabled.calls.count()).toBe(1);
expect(settingsService.ifEnabled).toHaveBeenCalledWith('STEPS.step_4_enabled', true, true);
expect(novaExtensionsService.ifNameEnabled.calls.count()).toBe(1);
expect(novaExtensionsService.ifNameEnabled).toHaveBeenCalledWith('foo-novaExtension');
});
it('step checkReadiness function returns true when promise is resolved', function() {