Remove deprecated auth-related api extensions
* Delete the accounts and users extensions * Delete associated tests * Related to bp remove-deprecated-auth Change-Id: I429551dbb39ec569c6d2c229fa0c3cafd9e56f11
This commit is contained in:
@@ -1,100 +0,0 @@
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 webob.exc
|
||||
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api.openstack import xmlutil
|
||||
from nova.auth import manager
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
LOG = logging.getLogger(__name__)
|
||||
authorize = extensions.extension_authorizer('compute', 'accounts')
|
||||
|
||||
|
||||
class AccountTemplate(xmlutil.TemplateBuilder):
|
||||
def construct(self):
|
||||
root = xmlutil.TemplateElement('account', selector='account')
|
||||
root.set('id', 'id')
|
||||
root.set('name', 'name')
|
||||
root.set('description', 'description')
|
||||
root.set('manager', 'manager')
|
||||
|
||||
return xmlutil.MasterTemplate(root, 1)
|
||||
|
||||
|
||||
def _translate_keys(account):
|
||||
return dict(id=account.id,
|
||||
name=account.name,
|
||||
description=account.description,
|
||||
manager=account.project_manager_id)
|
||||
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
self.manager = manager.AuthManager()
|
||||
|
||||
def index(self, req):
|
||||
raise webob.exc.HTTPNotImplemented()
|
||||
|
||||
@wsgi.serializers(xml=AccountTemplate)
|
||||
def show(self, req, id):
|
||||
"""Return data about the given account id"""
|
||||
authorize(req.environ['nova.context'])
|
||||
account = self.manager.get_project(id)
|
||||
return dict(account=_translate_keys(account))
|
||||
|
||||
def delete(self, req, id):
|
||||
authorize(req.environ['nova.context'])
|
||||
self.manager.delete_project(id)
|
||||
return {}
|
||||
|
||||
def create(self, req, body):
|
||||
"""We use update with create-or-update semantics
|
||||
because the id comes from an external source"""
|
||||
raise webob.exc.HTTPNotImplemented()
|
||||
|
||||
@wsgi.serializers(xml=AccountTemplate)
|
||||
def update(self, req, id, body):
|
||||
"""This is really create or update."""
|
||||
authorize(req.environ['nova.context'])
|
||||
description = body['account'].get('description')
|
||||
manager = body['account'].get('manager')
|
||||
try:
|
||||
account = self.manager.get_project(id)
|
||||
self.manager.modify_project(id, manager, description)
|
||||
except exception.NotFound:
|
||||
account = self.manager.create_project(id, manager, description)
|
||||
return dict(account=_translate_keys(account))
|
||||
|
||||
|
||||
class Accounts(extensions.ExtensionDescriptor):
|
||||
"""Admin-only access to accounts"""
|
||||
|
||||
name = "Accounts"
|
||||
alias = "os-accounts"
|
||||
namespace = "http://docs.openstack.org/compute/ext/accounts/api/v1.1"
|
||||
updated = "2011-12-23T00:00:00+00:00"
|
||||
|
||||
def get_resources(self):
|
||||
#TODO(bcwaldon): This should be prefixed with 'os-'
|
||||
res = extensions.ResourceExtension('accounts', Controller())
|
||||
return [res]
|
||||
@@ -1,141 +0,0 @@
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 webob import exc
|
||||
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api.openstack import xmlutil
|
||||
from nova.auth import manager
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
LOG = logging.getLogger(__name__)
|
||||
authorize = extensions.extension_authorizer('compute', 'users')
|
||||
|
||||
|
||||
def make_user(elem):
|
||||
elem.set('id')
|
||||
elem.set('name')
|
||||
elem.set('access')
|
||||
elem.set('secret')
|
||||
elem.set('admin')
|
||||
|
||||
|
||||
class UserTemplate(xmlutil.TemplateBuilder):
|
||||
def construct(self):
|
||||
root = xmlutil.TemplateElement('user', selector='user')
|
||||
make_user(root)
|
||||
return xmlutil.MasterTemplate(root, 1)
|
||||
|
||||
|
||||
class UsersTemplate(xmlutil.TemplateBuilder):
|
||||
def construct(self):
|
||||
root = xmlutil.TemplateElement('users')
|
||||
elem = xmlutil.SubTemplateElement(root, 'user', selector='users')
|
||||
make_user(elem)
|
||||
return xmlutil.MasterTemplate(root, 1)
|
||||
|
||||
|
||||
def _translate_keys(user):
|
||||
return dict(id=user.id,
|
||||
name=user.name,
|
||||
access=user.access,
|
||||
secret=user.secret,
|
||||
admin=user.admin)
|
||||
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
self.manager = manager.AuthManager()
|
||||
|
||||
@wsgi.serializers(xml=UsersTemplate)
|
||||
def index(self, req):
|
||||
"""Return all users in brief"""
|
||||
authorize(req.environ['nova.context'])
|
||||
users = self.manager.get_users()
|
||||
users = common.limited(users, req)
|
||||
users = [_translate_keys(user) for user in users]
|
||||
return dict(users=users)
|
||||
|
||||
@wsgi.serializers(xml=UsersTemplate)
|
||||
def detail(self, req):
|
||||
"""Return all users in detail"""
|
||||
return self.index(req)
|
||||
|
||||
@wsgi.serializers(xml=UserTemplate)
|
||||
def show(self, req, id):
|
||||
"""Return data about the given user id"""
|
||||
authorize(req.environ['nova.context'])
|
||||
|
||||
#NOTE(justinsb): The drivers are a little inconsistent in how they
|
||||
# deal with "NotFound" - some throw, some return None.
|
||||
try:
|
||||
user = self.manager.get_user(id)
|
||||
except exception.NotFound:
|
||||
user = None
|
||||
|
||||
if user is None:
|
||||
raise exc.HTTPNotFound()
|
||||
|
||||
return dict(user=_translate_keys(user))
|
||||
|
||||
def delete(self, req, id):
|
||||
authorize(req.environ['nova.context'])
|
||||
self.manager.delete_user(id)
|
||||
return {}
|
||||
|
||||
@wsgi.serializers(xml=UserTemplate)
|
||||
def create(self, req, body):
|
||||
authorize(req.environ['nova.context'])
|
||||
is_admin = body['user'].get('admin') in ('T', 'True', True)
|
||||
name = body['user'].get('name')
|
||||
access = body['user'].get('access')
|
||||
secret = body['user'].get('secret')
|
||||
user = self.manager.create_user(name, access, secret, is_admin)
|
||||
return dict(user=_translate_keys(user))
|
||||
|
||||
@wsgi.serializers(xml=UserTemplate)
|
||||
def update(self, req, id, body):
|
||||
authorize(req.environ['nova.context'])
|
||||
is_admin = body['user'].get('admin')
|
||||
if is_admin is not None:
|
||||
is_admin = is_admin in ('T', 'True', True)
|
||||
access = body['user'].get('access')
|
||||
secret = body['user'].get('secret')
|
||||
self.manager.modify_user(id, access, secret, is_admin)
|
||||
return dict(user=_translate_keys(self.manager.get_user(id)))
|
||||
|
||||
|
||||
class Users(extensions.ExtensionDescriptor):
|
||||
"""Allow admins to acces user information"""
|
||||
|
||||
name = "Users"
|
||||
alias = "os-users"
|
||||
namespace = "http://docs.openstack.org/compute/ext/users/api/v1.1"
|
||||
updated = "2011-08-08T00:00:00+00:00"
|
||||
|
||||
def get_resources(self):
|
||||
coll_actions = {'detail': 'GET'}
|
||||
res = extensions.ResourceExtension('users',
|
||||
Controller(),
|
||||
collection_actions=coll_actions)
|
||||
|
||||
return [res]
|
||||
@@ -1,153 +0,0 @@
|
||||
# Copyright 2010 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 lxml import etree
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.compute.contrib import accounts
|
||||
from nova.auth import manager as auth_manager
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import test
|
||||
from nova.tests.api.openstack import fakes
|
||||
|
||||
|
||||
def fake_init(self):
|
||||
self.manager = fakes.FakeAuthManager()
|
||||
|
||||
|
||||
class AccountsTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(AccountsTest, self).setUp()
|
||||
self.flags(verbose=True)
|
||||
self.stubs.Set(accounts.Controller, '__init__',
|
||||
fake_init)
|
||||
fakes.FakeAuthManager.clear_fakes()
|
||||
fakes.FakeAuthDatabase.data = {}
|
||||
fakes.stub_out_networking(self.stubs)
|
||||
fakes.stub_out_rate_limiting(self.stubs)
|
||||
|
||||
fakemgr = fakes.FakeAuthManager()
|
||||
joeuser = auth_manager.User('id1', 'guy1', 'acc1', 'secret1', False)
|
||||
superuser = auth_manager.User('id2', 'guy2', 'acc2', 'secret2', True)
|
||||
fakemgr.add_user(joeuser)
|
||||
fakemgr.add_user(superuser)
|
||||
fakemgr.create_project('test1', joeuser)
|
||||
fakemgr.create_project('test2', superuser)
|
||||
|
||||
def test_get_account(self):
|
||||
req = webob.Request.blank('/v2/fake/accounts/test1')
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = jsonutils.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_dict['account']['id'], 'test1')
|
||||
self.assertEqual(res_dict['account']['name'], 'test1')
|
||||
self.assertEqual(res_dict['account']['manager'], 'id1')
|
||||
|
||||
def test_get_account_xml(self):
|
||||
req = webob.Request.blank('/v2/fake/accounts/test1.xml')
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_tree = etree.fromstring(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual('account', res_tree.tag)
|
||||
self.assertEqual('test1', res_tree.get('id'))
|
||||
self.assertEqual('test1', res_tree.get('name'))
|
||||
self.assertEqual('id1', res_tree.get('manager'))
|
||||
|
||||
def test_account_delete(self):
|
||||
req = webob.Request.blank('/v2/fake/accounts/test1')
|
||||
req.method = 'DELETE'
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
self.assertTrue('test1' not in fakes.FakeAuthManager.projects)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
|
||||
def test_account_create(self):
|
||||
body = dict(account=dict(description='test account',
|
||||
manager='id1'))
|
||||
req = webob.Request.blank('/v2/fake/accounts/newacct')
|
||||
req.headers["Content-Type"] = "application/json"
|
||||
req.method = 'PUT'
|
||||
req.body = jsonutils.dumps(body)
|
||||
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = jsonutils.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_dict['account']['id'], 'newacct')
|
||||
self.assertEqual(res_dict['account']['name'], 'newacct')
|
||||
self.assertEqual(res_dict['account']['description'], 'test account')
|
||||
self.assertEqual(res_dict['account']['manager'], 'id1')
|
||||
self.assertTrue('newacct' in
|
||||
fakes.FakeAuthManager.projects)
|
||||
self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 3)
|
||||
|
||||
def test_account_create_xml(self):
|
||||
body = dict(account=dict(description='test account',
|
||||
manager='id1'))
|
||||
req = webob.Request.blank('/v2/fake/accounts/newacct.xml')
|
||||
req.headers["Content-Type"] = "application/json"
|
||||
req.method = 'PUT'
|
||||
req.body = jsonutils.dumps(body)
|
||||
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_tree = etree.fromstring(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_tree.tag, 'account')
|
||||
self.assertEqual(res_tree.get('id'), 'newacct')
|
||||
self.assertEqual(res_tree.get('name'), 'newacct')
|
||||
self.assertEqual(res_tree.get('description'), 'test account')
|
||||
self.assertEqual(res_tree.get('manager'), 'id1')
|
||||
self.assertTrue('newacct' in
|
||||
fakes.FakeAuthManager.projects)
|
||||
self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 3)
|
||||
|
||||
def test_account_update(self):
|
||||
body = dict(account=dict(description='test account',
|
||||
manager='id2'))
|
||||
req = webob.Request.blank('/v2/fake/accounts/test1')
|
||||
req.headers["Content-Type"] = "application/json"
|
||||
req.method = 'PUT'
|
||||
req.body = jsonutils.dumps(body)
|
||||
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = jsonutils.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_dict['account']['id'], 'test1')
|
||||
self.assertEqual(res_dict['account']['name'], 'test1')
|
||||
self.assertEqual(res_dict['account']['description'], 'test account')
|
||||
self.assertEqual(res_dict['account']['manager'], 'id2')
|
||||
self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 2)
|
||||
|
||||
def test_account_update_xml(self):
|
||||
body = dict(account=dict(description='test account',
|
||||
manager='id2'))
|
||||
req = webob.Request.blank('/v2/fake/accounts/test1.xml')
|
||||
req.headers["Content-Type"] = "application/json"
|
||||
req.method = 'PUT'
|
||||
req.body = jsonutils.dumps(body)
|
||||
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_tree = etree.fromstring(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_tree.tag, 'account')
|
||||
self.assertEqual(res_tree.get('id'), 'test1')
|
||||
self.assertEqual(res_tree.get('name'), 'test1')
|
||||
self.assertEqual(res_tree.get('description'), 'test account')
|
||||
self.assertEqual(res_tree.get('manager'), 'id2')
|
||||
self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 2)
|
||||
@@ -1,150 +0,0 @@
|
||||
# Copyright 2010 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 lxml import etree
|
||||
|
||||
from nova.api.openstack.compute.contrib import users
|
||||
import nova.auth.manager as auth_manager
|
||||
from nova import test
|
||||
from nova.tests.api.openstack import fakes
|
||||
from nova import utils
|
||||
|
||||
|
||||
def fake_init(self):
|
||||
self.manager = fakes.FakeAuthManager()
|
||||
|
||||
|
||||
class UsersTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(UsersTest, self).setUp()
|
||||
self.flags(verbose=True)
|
||||
self.stubs.Set(users.Controller, '__init__',
|
||||
fake_init)
|
||||
fakes.FakeAuthManager.clear_fakes()
|
||||
fakes.FakeAuthManager.projects = dict(testacct=auth_manager.Project(
|
||||
'testacct',
|
||||
'testacct',
|
||||
'id1',
|
||||
'test',
|
||||
[]))
|
||||
fakes.FakeAuthDatabase.data = {}
|
||||
fakes.stub_out_networking(self.stubs)
|
||||
fakes.stub_out_rate_limiting(self.stubs)
|
||||
|
||||
fakemgr = fakes.FakeAuthManager()
|
||||
fakemgr.add_user(auth_manager.User('id1', 'guy1',
|
||||
'acc1', 'secret1', False))
|
||||
fakemgr.add_user(auth_manager.User('id2', 'guy2',
|
||||
'acc2', 'secret2', True))
|
||||
|
||||
self.controller = users.Controller()
|
||||
|
||||
def test_get_user_list(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/users')
|
||||
res_dict = self.controller.index(req)
|
||||
|
||||
self.assertEqual(len(res_dict['users']), 2)
|
||||
|
||||
def test_get_user_by_id(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/users/id2')
|
||||
res_dict = self.controller.show(req, 'id2')
|
||||
|
||||
self.assertEqual(res_dict['user']['id'], 'id2')
|
||||
self.assertEqual(res_dict['user']['name'], 'guy2')
|
||||
self.assertEqual(res_dict['user']['secret'], 'secret2')
|
||||
self.assertEqual(res_dict['user']['admin'], True)
|
||||
|
||||
def test_user_delete(self):
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/users/id1')
|
||||
self.controller.delete(req, 'id1')
|
||||
|
||||
self.assertTrue('id1' not in [u.id for u in
|
||||
fakes.FakeAuthManager.auth_data])
|
||||
|
||||
def test_user_create(self):
|
||||
secret = utils.generate_password()
|
||||
body = dict(user=dict(name='test_guy',
|
||||
access='acc3',
|
||||
secret=secret,
|
||||
admin=True))
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/users')
|
||||
res_dict = self.controller.create(req, body)
|
||||
|
||||
# NOTE(justinsb): This is a questionable assertion in general
|
||||
# fake sets id=name, but others might not...
|
||||
self.assertEqual(res_dict['user']['id'], 'test_guy')
|
||||
|
||||
self.assertEqual(res_dict['user']['name'], 'test_guy')
|
||||
self.assertEqual(res_dict['user']['access'], 'acc3')
|
||||
self.assertEqual(res_dict['user']['secret'], secret)
|
||||
self.assertEqual(res_dict['user']['admin'], True)
|
||||
self.assertTrue('test_guy' in [u.id for u in
|
||||
fakes.FakeAuthManager.auth_data])
|
||||
self.assertEqual(len(fakes.FakeAuthManager.auth_data), 3)
|
||||
|
||||
def test_user_update(self):
|
||||
new_secret = utils.generate_password()
|
||||
body = dict(user=dict(name='guy2',
|
||||
access='acc2',
|
||||
secret=new_secret))
|
||||
|
||||
req = fakes.HTTPRequest.blank('/v2/fake/users/id2')
|
||||
res_dict = self.controller.update(req, 'id2', body)
|
||||
|
||||
self.assertEqual(res_dict['user']['id'], 'id2')
|
||||
self.assertEqual(res_dict['user']['name'], 'guy2')
|
||||
self.assertEqual(res_dict['user']['access'], 'acc2')
|
||||
self.assertEqual(res_dict['user']['secret'], new_secret)
|
||||
self.assertEqual(res_dict['user']['admin'], True)
|
||||
|
||||
|
||||
class TestUsersXMLSerializer(test.TestCase):
|
||||
|
||||
def test_index(self):
|
||||
serializer = users.UsersTemplate()
|
||||
fixture = {'users': [{'id': 'id1',
|
||||
'name': 'guy1',
|
||||
'secret': 'secret1',
|
||||
'admin': False},
|
||||
{'id': 'id2',
|
||||
'name': 'guy2',
|
||||
'secret': 'secret2',
|
||||
'admin': True}]}
|
||||
|
||||
output = serializer.serialize(fixture)
|
||||
res_tree = etree.XML(output)
|
||||
|
||||
self.assertEqual(res_tree.tag, 'users')
|
||||
self.assertEqual(len(res_tree), 2)
|
||||
self.assertEqual(res_tree[0].tag, 'user')
|
||||
self.assertEqual(res_tree[0].get('id'), 'id1')
|
||||
self.assertEqual(res_tree[1].tag, 'user')
|
||||
self.assertEqual(res_tree[1].get('id'), 'id2')
|
||||
|
||||
def test_show(self):
|
||||
serializer = users.UserTemplate()
|
||||
fixture = {'user': {'id': 'id2',
|
||||
'name': 'guy2',
|
||||
'secret': 'secret2',
|
||||
'admin': True}}
|
||||
|
||||
output = serializer.serialize(fixture)
|
||||
res_tree = etree.XML(output)
|
||||
|
||||
self.assertEqual(res_tree.tag, 'user')
|
||||
self.assertEqual(res_tree.get('id'), 'id2')
|
||||
self.assertEqual(res_tree.get('name'), 'guy2')
|
||||
self.assertEqual(res_tree.get('secret'), 'secret2')
|
||||
self.assertEqual(res_tree.get('admin'), 'True')
|
||||
@@ -151,7 +151,6 @@ class ExtensionControllerTest(ExtensionTestCase):
|
||||
def setUp(self):
|
||||
super(ExtensionControllerTest, self).setUp()
|
||||
self.ext_list = [
|
||||
"Accounts",
|
||||
"AdminActions",
|
||||
"Aggregates",
|
||||
"Certificates",
|
||||
@@ -182,7 +181,6 @@ class ExtensionControllerTest(ExtensionTestCase):
|
||||
"ServerDiagnostics",
|
||||
"ServerStartStop",
|
||||
"SimpleTenantUsage",
|
||||
"Users",
|
||||
"VirtualInterfaces",
|
||||
"Volumes",
|
||||
"VolumeTypes",
|
||||
|
||||
Reference in New Issue
Block a user