Read access to config via REST

We have a lot of new angular widgets and panels coming, and some of them
will need access to configs stored in settings. Right now, the default way to
get them is through _conf.html or _script.html. We should really fetch them
through the new REST layer instead. This ensures we are following the same
pattern already set up for angular panels and services.

This version:
- add localstorage for caching config front-end

Change-Id: I94ce8ef3e8367be99bbba2f6ddd7e4529d819d58
Co-Authored-By: Richard Jones <r1chardj0n3s@gmail.com>
Implements: blueprint config-restful
This commit is contained in:
Thai Tran 2015-02-23 17:36:55 -08:00
parent f38965ec30
commit 12a7f1d3fc
5 changed files with 207 additions and 0 deletions

View File

@ -0,0 +1,70 @@
/*
Copyright 2015, Rackspace, US, 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';
/**
* @ngdoc service
* @name hz.api.configAPI
* @description Provides access to dashboard configuration.
*/
function ConfigAPI(apiService) {
/**
* @name hz.api.configAPI.getUserDefaults
* @description
* Get the default user configuration settings.
*
* Returns an object with user configuration settings.
*/
this.getUserDefaults = function() {
return apiService.get('/api/config/user/')
.success(function(data) {
// store config in localStorage
// should be call only when defaults are needed
// or when user wants to reset it
localStorage.user_config = angular.toJson(data);
})
.error(function () {
horizon.alert('error', gettext('Unable to retrieve user configuration.'));
});
};
/**
* @name hz.api.configAPI.getAdminDefaults
* @description
* Get the default admin configuration settings.
*
* Returns an object with admin configuration settings.
*/
this.getAdminDefaults = function(params) {
return apiService.get('/api/config/admin/')
.success(function(data) {
// store this in localStorage
// should be call once each page load
localStorage.admin_config = angular.toJson(data);
})
.error(function () {
horizon.alert('error', gettext('Unable to retrieve admin configuration.'));
});
};
}
// Register it with the API module so that anybody using the
// API module will have access to the Config APIs.
angular.module('hz.api')
.service('configAPI', ['apiService', ConfigAPI]);
}());

View File

@ -21,6 +21,7 @@
<script src='{{ STATIC_URL }}horizon/js/angular/hz.api.module.js'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/services/hz.api.service.js'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/services/hz.api.cinder.js'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/services/hz.api.config.js'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/services/hz.api.glance.js'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/services/hz.api.keystone.js'></script>
<script src='{{ STATIC_URL }}horizon/js/angular/services/hz.api.nova.js'></script>

View File

@ -23,6 +23,7 @@ in https://wiki.openstack.org/wiki/APIChangeGuidelines.
# import REST API modules here
import cinder #flake8: noqa
import config #flake8: noqa
import glance #flake8: noqa
import keystone #flake8: noqa
import network #flake8: noqa

View File

@ -0,0 +1,72 @@
# Copyright 2015 IBM Corp.
#
# 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.
from django.views import generic
from horizon import conf
from openstack_dashboard.api.rest import urls
from openstack_dashboard.api.rest import utils as rest_utils
# properties we know are admin config
admin_configs = ['ajax_queue_limit', 'ajax_poll_interval',
'user_home', 'help_url',
'password_autocomplete', 'disable_password_reveal']
# properties we know are user config
# this is a white list of keys under HORIZON_CONFIG in settings.pys
# that we want to pass onto client
user_configs = ['auto_fade_alerts', 'modal_backdrop']
@urls.register
class DefaultUserConfigs(generic.View):
"""API for retrieving user configurations.
This API returns read-only-default configuration values.
This configuration object is ideally fetched once per application life
or when a user needs to restore the default values.
Examples of user config: modal_backdrop, disable_password_reveal
"""
url_regex = r'config/user/$'
@rest_utils.ajax()
def get(self, request):
"""Get default user configurations
"""
config = {}
for key in user_configs:
config[key] = conf.HORIZON_CONFIG.get(key, None)
return config
@urls.register
class AdminConfigs(generic.View):
"""API for retrieving admin configurations.
This API returns read-only admin configuration values.
This configuration object can be fetched as needed.
Examples of admin config: help_url, user_home
"""
url_regex = r'config/admin/$'
@rest_utils.ajax()
def get(self, request):
"""Get read-only admin configurations
"""
config = {}
for key in admin_configs:
config[key] = conf.HORIZON_CONFIG.get(key, None)
return config

View File

@ -0,0 +1,63 @@
# Copyright 2015 IBM Corp.
#
# 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.
import mock
from horizon import conf
from openstack_dashboard.api.rest import config
from openstack_dashboard.test.api_tests import rest_test_utils as util
from openstack_dashboard.test import helpers as test
class ConfigRestTestCase(test.RestAPITestCase):
def assertContains(self, response, expected_content):
if response.find(expected_content) > 0:
return
self.fail('%s does not contain %s' %
(response, expected_content))
def assertNotContains(self, response, expected_content):
if response.find(expected_content) < 0:
return
self.fail('%s contains %s when it should not' %
(response, expected_content))
def test_user_config_get(self):
user_config = {"modal_backdrop": "static"}
content = '"modal_backdrop": "static"'
with mock.patch.dict(conf.HORIZON_CONFIG, user_config):
request = util.construct_request()
response = config.DefaultUserConfigs().get(request)
self.assertStatusCode(response, 200)
self.assertContains(response.content, content)
def test_admin_config_get(self):
admin_config = {"user_home": "somewhere.com"}
content = '"user_home": "somewhere.com"'
with mock.patch.dict(conf.HORIZON_CONFIG, admin_config):
request = util.construct_request()
response = config.AdminConfigs().get(request)
self.assertStatusCode(response, 200)
self.assertContains(response.content, content)
def test_ignore_list(self):
ignore_config = {"password_validator": "someobject"}
content = '"password_validator": "someobject"'
with mock.patch.dict(conf.HORIZON_CONFIG, ignore_config):
request = util.construct_request()
response = config.AdminConfigs().get(request)
self.assertStatusCode(response, 200)
self.assertNotContains(response.content, content)