Fixed tech debt related to ClusterPluginLink

- move test from unit to integration;
- disable additional properties in validation schema;
- refactoring;
- add more documentation;
- add more tests;
- Cluster-level plugin dashboard entries is renames to the cluster plugin links;
- hidden field added to the ClusterPluginLink API;

Change-Id: I7dc99fc622359848e54c7ce248360db1bdef7f0f
Author:         Ilya Kutukov <ikutukov@mirantis.com>
Co-Authored-By: Vladimir Sharshov <vsharshov@mirantis.com>
Co-Authored-By: Ivan Kliuk <ikliuk@mirantis.com>
Closes-Bug: #1518381
This commit is contained in:
Vladimir Sharshov (warpc) 2015-11-20 19:19:30 +03:00 committed by Ilya Kutukov
parent 937741577c
commit 5b5acc97f3
19 changed files with 322 additions and 293 deletions

View File

@ -16,17 +16,22 @@
from nailgun.api.v1.handlers import base
from nailgun.api.v1.handlers.base import content
from nailgun.api.v1.validators import dashboard_entry
from nailgun.api.v1.validators import cluster_plugin_link
from nailgun.errors import errors
from nailgun import objects
class DashboardEntryHandler(base.SingleHandler):
class ClusterPluginLinkHandler(base.SingleHandler):
validator = dashboard_entry.DashboardEntryValidator
single = objects.DashboardEntry
validator = cluster_plugin_link.ClusterPluginLinkValidator
single = objects.ClusterPluginLink
def GET(self, cluster_id, obj_id):
""":returns: JSONized REST object.
:http: * 200 (OK)
* 404 (dashboard entry not found in db)
"""
self.get_object_or_404(objects.Cluster, cluster_id)
obj = self.get_object_or_404(self.single, obj_id)
@ -37,6 +42,7 @@ class DashboardEntryHandler(base.SingleHandler):
""":returns: JSONized REST object.
:http: * 200 (OK)
* 400 (invalid object data specified)
* 404 (object not found in db)
"""
obj = self.get_object_or_404(self.single, obj_id)
@ -52,6 +58,7 @@ class DashboardEntryHandler(base.SingleHandler):
""":returns: JSONized REST object.
:http: * 200 (OK)
* 400 (invalid object data specified)
* 404 (object not found in db)
"""
return self.PUT(cluster_id, obj_id)
@ -60,7 +67,7 @@ class DashboardEntryHandler(base.SingleHandler):
def DELETE(self, cluster_id, obj_id):
""":returns: JSONized REST object.
:http: * 200 (OK)
:http: * 204 (OK)
* 404 (object not found in db)
"""
d_e = self.get_object_or_404(self.single, obj_id)
@ -68,14 +75,14 @@ class DashboardEntryHandler(base.SingleHandler):
raise self.http(204)
class DashboardEntryCollectionHandler(base.CollectionHandler):
class ClusterPluginLinkCollectionHandler(base.CollectionHandler):
collection = objects.DashboardEntryCollection
validator = dashboard_entry.DashboardEntryValidator
collection = objects.ClusterPluginLinkCollection
validator = cluster_plugin_link.ClusterPluginLinkValidator
@content
def GET(self, cluster_id):
""":returns: Collection of JSONized DashboardEntry objects.
""":returns: Collection of JSONized ClusterPluginLink objects.
:http: * 200 (OK)
* 404 (cluster not found in db)

View File

@ -38,10 +38,10 @@ from nailgun.api.v1.handlers.cluster import VmwareAttributesDefaultsHandler
from nailgun.api.v1.handlers.cluster import VmwareAttributesHandler
from nailgun.api.v1.handlers.component import ComponentCollectionHandler
from nailgun.api.v1.handlers.dashboard_entry \
import DashboardEntryCollectionHandler
from nailgun.api.v1.handlers.dashboard_entry \
import DashboardEntryHandler
from nailgun.api.v1.handlers.cluster_plugin_link \
import ClusterPluginLinkCollectionHandler
from nailgun.api.v1.handlers.cluster_plugin_link \
import ClusterPluginLinkHandler
from nailgun.api.v1.handlers.logs import LogEntryCollectionHandler
from nailgun.api.v1.handlers.logs import LogPackageDefaultConfig
@ -217,10 +217,10 @@ urls = (
r'/clusters/(?P<cluster_id>\d+)/vmware_attributes/defaults/?$',
VmwareAttributesDefaultsHandler,
r'/clusters/(?P<cluster_id>\d+)/dashboard_entries/?$',
DashboardEntryCollectionHandler,
r'/clusters/(?P<cluster_id>\d+)/dashboard_entries/(?P<obj_id>\d+)/?$',
DashboardEntryHandler,
r'/clusters/(?P<cluster_id>\d+)/plugin_links/?$',
ClusterPluginLinkCollectionHandler,
r'/clusters/(?P<cluster_id>\d+)/plugin_links/(?P<obj_id>\d+)/?$',
ClusterPluginLinkHandler,
r'/nodegroups/?$',
NodeGroupCollectionHandler,
@ -378,5 +378,5 @@ def public_urls():
r'/nodes/?$': ['POST'],
r'/nodes/agent/?$': ['PUT'],
r'/version/?$': ['GET'],
r'/clusters/(?P<cluster_id>\d+)/dashboard_entries/?$': ['POST']
r'/clusters/(?P<cluster_id>\d+)/plugin_links/?$': ['POST']
}

View File

@ -15,24 +15,28 @@
from nailgun.api.v1.validators.base import BasicValidator
from nailgun.api.v1.validators.json_schema import dashboard_entry
from nailgun.api.v1.validators.json_schema import cluster_plugin_link
class DashboardEntryValidator(BasicValidator):
collection_schema = dashboard_entry.DASHBOARD_ENTRIES_SCHEMA
class ClusterPluginLinkValidator(BasicValidator):
collection_schema = cluster_plugin_link.CLUSTER_PLUGIN_LINKS_SCHEMA
@classmethod
def validate(cls, data):
parsed = super(DashboardEntryValidator, cls).validate(data)
cls.validate_schema(parsed, dashboard_entry.DASHBOARD_ENTRY_SCHEMA)
parsed = super(ClusterPluginLinkValidator, cls).validate(data)
cls.validate_schema(
parsed,
cluster_plugin_link.CLUSTER_PLUGIN_LINK_SCHEMA
)
return parsed
@classmethod
def validate_update(cls, data, instance):
parsed = super(DashboardEntryValidator, cls).validate(data)
cls.validate_schema(parsed,
dashboard_entry.DASHBOARD_ENTRY_UPDATE_SCHEMA)
parsed = super(ClusterPluginLinkValidator, cls).validate(data)
cls.validate_schema(
parsed,
cluster_plugin_link.CLUSTER_PLUGIN_LINK_UPDATE_SCHEMA
)
return parsed
@classmethod

View File

@ -13,29 +13,33 @@
# License for the specific language governing permissions and limitations
# under the License.
DASHBOARD_ENTRY_SCHEMA = {
CLUSTER_PLUGIN_LINK_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'properties': {
'id': {'type': 'integer'},
'title': {'type': 'string', 'maxLength': 50, 'minLength': 1},
'url': {'type': 'string'},
'description': {'type': 'string'}
'description': {'type': 'string'},
'hidden': {'type': 'boolean'}
},
'required': ['title', 'url']
'required': ['title', 'url'],
'additionalProperties': False
}
DASHBOARD_ENTRIES_SCHEMA = {
CLUSTER_PLUGIN_LINKS_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'array',
'items': DASHBOARD_ENTRY_SCHEMA}
'items': CLUSTER_PLUGIN_LINK_SCHEMA}
DASHBOARD_ENTRY_UPDATE_SCHEMA = {
CLUSTER_PLUGIN_LINK_UPDATE_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'type': 'object',
'properties': {
'title': {'type': 'string', 'maxLength': 50, 'minLength': 1},
'url': {'type': 'string'},
'description': {'type': 'string'}
}
'description': {'type': 'string'},
'hidden': {'type': 'boolean'}
},
'additionalProperties': False
}

View File

@ -106,7 +106,7 @@ def upgrade():
upgrade_cluster_plugins()
upgrade_add_baremetal_net()
upgrade_with_components()
dashboard_entries_upgrade()
cluster_plugin_links_upgrade()
upgrade_master_settings()
upgrade_all_network_data_from_string_to_appropriate_data_type()
@ -114,7 +114,7 @@ def upgrade():
def downgrade():
downgrade_all_network_data_to_string()
downgrade_master_settings()
dashboard_entries_downgrade()
cluster_plugin_links_downgrade()
downgrade_with_components()
downgrade_add_baremetal_net()
downgrade_cluster_plugins()
@ -513,23 +513,25 @@ def downgrade_with_components():
op.drop_column('releases', 'components_metadata')
def dashboard_entries_upgrade():
def cluster_plugin_links_upgrade():
op.create_table(
'dashboard_entries',
'cluster_plugin_links',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('cluster_id', sa.Integer(), nullable=False),
sa.Column('title', sa.Text(), nullable=False),
sa.Column('url', sa.Text(), nullable=False),
sa.Column('description', sa.Text()),
sa.Column(
'hidden',
sa.Boolean(),
nullable=False,
server_default='false'
),
sa.ForeignKeyConstraint(['cluster_id'], ['clusters.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('dashboard_entries_cluster_id_key',
'dashboard_entries', ['cluster_id'])
def dashboard_entries_downgrade():
op.drop_table('dashboard_entries')
op.create_index('cluster_plugin_links_cluster_id_key',
'cluster_plugin_links', ['cluster_id'])
def upgrade_all_network_data_from_string_to_appropriate_data_type():
@ -592,3 +594,7 @@ def ip_type_to_string(table_name, column_name, string_len):
column_name,
string_len)
)
def cluster_plugin_links_downgrade():
op.drop_table('cluster_plugin_links')

View File

@ -43,7 +43,7 @@ from nailgun.db.sqlalchemy.models.network_config import NeutronConfig
from nailgun.db.sqlalchemy.models.network_config import NovaNetworkConfig
from nailgun.db.sqlalchemy.models.notification import Notification
from nailgun.db.sqlalchemy.models.dashboard_entry import DashboardEntry
from nailgun.db.sqlalchemy.models.cluster_plugin_link import ClusterPluginLink
from nailgun.db.sqlalchemy.models.task import Task

View File

@ -88,8 +88,8 @@ class Cluster(Base):
nodes = relationship(
"Node", backref="cluster", cascade="delete", order_by='Node.id')
tasks = relationship("Task", backref="cluster", cascade="delete")
dashboard_entries = relationship(
"DashboardEntry", backref="cluster", cascade="delete")
plugin_links = relationship(
"ClusterPluginLink", backref="cluster", cascade="delete")
attributes = relationship("Attributes", uselist=False,
backref="cluster", cascade="delete")
changes_list = relationship("ClusterChanges", backref="cluster",

View File

@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
@ -22,10 +23,11 @@ from sqlalchemy import Text
from nailgun.db.sqlalchemy.models.base import Base
class DashboardEntry(Base):
__tablename__ = 'dashboard_entries'
class ClusterPluginLink(Base):
__tablename__ = 'cluster_plugin_links'
id = Column(Integer, primary_key=True)
cluster_id = Column(Integer, ForeignKey('clusters.id'))
cluster_id = Column(Integer, ForeignKey('clusters.id'), nullable=False)
title = Column(Text, nullable=False)
url = Column(Text, nullable=False)
description = Column(Text)
hidden = Column(Boolean, default=False)

View File

@ -55,5 +55,5 @@ from nailgun.objects.plugin import ClusterPlugins
from nailgun.objects.network_group import NetworkGroup
from nailgun.objects.network_group import NetworkGroupCollection
from nailgun.objects.dashboard_entry import DashboardEntry
from nailgun.objects.dashboard_entry import DashboardEntryCollection
from nailgun.objects.cluster_plugin_link import ClusterPluginLink
from nailgun.objects.cluster_plugin_link import ClusterPluginLinkCollection

View File

@ -14,27 +14,28 @@
# License for the specific language governing permissions and limitations
# under the License.
from nailgun.db.sqlalchemy.models import dashboard_entry \
as dashboard_entry_db_model
from nailgun.db.sqlalchemy.models import cluster_plugin_link \
as cluster_plugin_link_db_model
from nailgun.objects import base
from nailgun.objects.serializers import dashboard_entry
from nailgun.objects.serializers import cluster_plugin_link
class DashboardEntry(base.NailgunObject):
class ClusterPluginLink(base.NailgunObject):
model = dashboard_entry_db_model.DashboardEntry
serializer = dashboard_entry.DashboardEntrySerializer
model = cluster_plugin_link_db_model.ClusterPluginLink
serializer = cluster_plugin_link.ClusterPluginLinkSerializer
class DashboardEntryCollection(base.NailgunCollection):
class ClusterPluginLinkCollection(base.NailgunCollection):
single = DashboardEntry
single = ClusterPluginLink
@classmethod
def get_by_cluster_id(cls, cluster_id):
if cluster_id == '':
return cls.filter_by(None, cluster_id=None)
return cls.filter_by(None, cluster_id=cluster_id)
if cluster_id is not None:
return cls.filter_by(None, cluster_id=cluster_id)
else:
return cls.all()
@classmethod
def create_with_cluster_id(cls, data, cluster_id):

View File

@ -17,11 +17,12 @@
from nailgun.objects.serializers.base import BasicSerializer
class DashboardEntrySerializer(BasicSerializer):
class ClusterPluginLinkSerializer(BasicSerializer):
fields = (
"id",
"title",
"url",
"description"
"description",
"hidden"
)

View File

@ -195,8 +195,8 @@ class InstallationInfo(object):
vmware_attributes_editable,
self.vmware_attributes_white_list
),
'dashboard_entries': self.get_dashboard_entries(
cluster.dashboard_entries),
'plugin_links': self.get_cluster_plugin_links(
cluster.plugin_links),
'net_provider': cluster.net_provider,
'fuel_version': cluster.fuel_version,
'is_customized': cluster.is_customized,
@ -306,9 +306,9 @@ class InstallationInfo(object):
groups_info.append(group_info)
return groups_info
def get_dashboard_entries(self, dashboard_entries):
def get_cluster_plugin_links(self, plugin_links):
return [{'title': e.title, 'description': e.description, 'id': e.id}
for e in dashboard_entries]
for e in plugin_links]
def get_installation_info(self):
clusters_info = self.get_clusters_info()

View File

@ -23,6 +23,7 @@ except ImportError:
import mock
import os
import re
import six
import time
import uuid
@ -53,7 +54,7 @@ from nailgun.logger import logger
from nailgun.db.sqlalchemy.fixman import load_fake_deployment_tasks
from nailgun.db.sqlalchemy.fixman import load_fixture
from nailgun.db.sqlalchemy.fixman import upload_fixture
from nailgun.db.sqlalchemy.models import DashboardEntry
from nailgun.db.sqlalchemy.models import ClusterPluginLink
from nailgun.db.sqlalchemy.models import NodeAttributes
from nailgun.db.sqlalchemy.models import NodeNICInterface
from nailgun.db.sqlalchemy.models import Notification
@ -447,22 +448,23 @@ class EnvironmentManager(object):
ClusterPlugins.set_attributes(cluster.id, plugin.id, enabled=True)
return plugin
def create_dashboard_entry(self, **kwargs):
def create_cluster_plugin_link(self, **kwargs):
dash_data = {
"title": "title",
"url": "url",
"description": "description",
"cluster_id": None
"cluster_id": None,
"hidden": False
}
if kwargs:
dash_data.update(kwargs)
dashboard_entry = DashboardEntry()
dashboard_entry.cluster_id = dash_data.get("cluster_id")
for f, v in dash_data.iteritems():
setattr(dashboard_entry, f, v)
self.db.add(dashboard_entry)
cluster_plugin_link = ClusterPluginLink()
cluster_plugin_link.cluster_id = dash_data.get("cluster_id")
for f, v in six.iteritems(dash_data):
setattr(cluster_plugin_link, f, v)
self.db.add(cluster_plugin_link)
self.db.commit()
return dashboard_entry
return cluster_plugin_link
def default_metadata(self):
item = self.find_item_by_pk_model(

View File

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Mirantis, 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.
from nailgun.test.base import BaseIntegrationTest
from nailgun.utils import reverse
from oslo.serialization import jsonutils
class TestAssignmentHandlers(BaseIntegrationTest):
def setUp(self):
super(TestAssignmentHandlers, self).setUp()
self.cluster = self.env.create(
cluster_kwargs={"api": True},
nodes_kwargs=[{}]
)
self.cluster_data = {
'title': 'test title',
'url': 'http://test.com/url',
'description': 'short description'
}
def test_cluster_plugin_links_list_empty(self):
resp = self.app.get(
reverse(
'ClusterPluginLinkCollectionHandler',
kwargs={'cluster_id': self.cluster['id']}
),
headers=self.default_headers
)
self.assertEqual(200, resp.status_code)
self.assertItemsEqual([], resp.json_body)
def test_cluster_plugin_link_creation(self):
resp = self.app.post(
reverse(
'ClusterPluginLinkCollectionHandler',
kwargs={'cluster_id': self.cluster['id']}
),
params=jsonutils.dumps(self.cluster_data),
headers=self.default_headers
)
self.assertEqual(201, resp.status_code)
plugin_link = self.env.clusters[0].plugin_links[0]
self.assertEqual(self.cluster_data['title'], plugin_link.title)
self.assertEqual(self.cluster_data['url'], plugin_link.url)
self.assertEqual(
self.cluster_data['description'],
plugin_link.description
)
def test_cluster_plugin_link_fail_creation(self):
resp = self.app.post(
reverse(
'ClusterPluginLinkCollectionHandler',
kwargs={'cluster_id': self.cluster['id']}
),
jsonutils.dumps({
'title': self.cluster_data['title'],
'description': self.cluster_data['description']
}),
headers=self.default_headers,
expect_errors=True
)
self.assertEqual(400, resp.status_code)
self.assertItemsEqual([], self.env.clusters[0].plugin_links)

View File

@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Mirantis, 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.
from nailgun.db.sqlalchemy.models.cluster_plugin_link import ClusterPluginLink
from nailgun.test.base import BaseIntegrationTest
from nailgun.utils import reverse
from oslo.serialization import jsonutils
class TestHandlers(BaseIntegrationTest):
def setUp(self):
super(TestHandlers, self).setUp()
self.cluster = self.env.create_cluster(api=False)
self.cluster_plugin_link = self.env \
.create_cluster_plugin_link(cluster_id=self.cluster.id)
def test_cluster_plugin_link_update(self):
cluster_plugin_link_update = {
'title': 'new title 2',
'description': 'new description 2'
}
resp = self.app.put(
reverse(
'ClusterPluginLinkHandler',
kwargs={'cluster_id': self.cluster['id'],
'obj_id': self.cluster_plugin_link.id}
),
jsonutils.dumps(cluster_plugin_link_update),
headers=self.default_headers
)
self.assertEqual(self.cluster_plugin_link.id, resp.json_body['id'])
self.assertEqual('new title 2', resp.json_body['title'])
self.assertEqual('new description 2', resp.json_body['description'])
self.assertEqual(self.cluster_plugin_link.url, resp.json_body['url'])
def test_cluster_plugin_link_get_with_cluster(self):
resp = self.app.get(
reverse(
'ClusterPluginLinkHandler',
kwargs={'cluster_id': self.cluster['id'],
'obj_id': self.cluster_plugin_link.id}
),
headers=self.default_headers
)
self.assertEqual(200, resp.status_code)
self.assertEqual(self.cluster_plugin_link.id, resp.json_body['id'])
self.assertEqual(self.cluster_plugin_link.title,
resp.json_body['title'])
self.assertEqual(self.cluster_plugin_link.url, resp.json_body['url'])
self.assertEqual(self.cluster_plugin_link.description,
resp.json_body['description'])
self.assertEqual(self.cluster_plugin_link.hidden,
resp.json_body['hidden'])
def test_cluster_plugin_link_not_found(self):
resp = self.app.get(
reverse(
'ClusterPluginLinkHandler',
kwargs={'cluster_id': self.cluster['id'],
'obj_id': self.cluster_plugin_link.id + 1}
),
headers=self.default_headers,
expect_errors=True
)
self.assertEqual(404, resp.status_code)
def test_cluster_plugin_link_delete(self):
resp = self.app.delete(
reverse(
'ClusterPluginLinkHandler',
kwargs={'cluster_id': self.cluster['id'],
'obj_id': self.cluster_plugin_link.id}
),
headers=self.default_headers,
)
self.assertEqual(204, resp.status_code)
d_e_query = self.db.query(ClusterPluginLink) \
.filter_by(cluster_id=self.cluster.id)
self.assertEquals(d_e_query.count(), 0)
def test_cluster_plugin_link_patch(self):
cluster_plugin_link_update = {
'title': 'new title 3',
'description': 'new description 3',
'hidden': True
}
resp = self.app.patch(
reverse(
'ClusterPluginLinkHandler',
kwargs={'cluster_id': self.cluster['id'],
'obj_id': self.cluster_plugin_link.id}
),
jsonutils.dumps(cluster_plugin_link_update),
headers=self.default_headers
)
self.assertEqual(self.cluster_plugin_link.id, resp.json_body['id'])
self.assertEqual('new title 3', resp.json_body['title'])
self.assertEqual('new description 3', resp.json_body['description'])
self.assertEqual(self.cluster_plugin_link.url, resp.json_body['url'])
self.assertEqual(True, resp.json_body['hidden'])

View File

@ -371,6 +371,7 @@ class TestInstallationInfo(BaseTestCase):
('plugins', 'installed_plugins'),
('networking_configs', 'network_configuration'),
('release_id', 'release'),
('cluster_plugin_links', 'plugin_links'),
)
for name_from, name_to in rename_fields:
cluster_schema.pop(name_from)

View File

@ -1,90 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Mirantis, 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.
from nailgun.test.base import BaseIntegrationTest
from nailgun.utils import reverse
from oslo.serialization import jsonutils
class TestAssignmentHandlers(BaseIntegrationTest):
def test_dashboard_entries_list_empty(self):
cluster = self.env.create(
cluster_kwargs={"api": True},
nodes_kwargs=[{}]
)
resp = self.app.get(
reverse(
'DashboardEntryCollectionHandler',
kwargs={'cluster_id': cluster['id']}
),
headers=self.default_headers
)
self.assertEqual(200, resp.status_code)
self.assertEqual([], resp.json_body)
def test_dashboard_entry_creation(self):
cluster = self.env.create(
cluster_kwargs={"api": True},
nodes_kwargs=[{}]
)
title = 'test title'
url = 'http://test.com/url'
description = 'short description'
resp = self.app.post(
reverse(
'DashboardEntryCollectionHandler',
kwargs={'cluster_id': cluster['id']}
),
params=jsonutils.dumps({
"title": title,
"url": url,
"description": description
}),
headers=self.default_headers
)
self.assertEqual(resp.status_code, 201)
dashboard_entry = self.env.clusters[0].dashboard_entries[0]
self.assertEqual(dashboard_entry.title, title)
self.assertEqual(dashboard_entry.url, url)
self.assertEqual(dashboard_entry.description, description)
def test_dashboard_entry_fail_creation(self):
cluster = self.env.create(
cluster_kwargs={"api": True},
nodes_kwargs=[{}]
)
title = 'test title'
description = 'short description'
resp = self.app.post(
reverse(
'DashboardEntryCollectionHandler',
kwargs={'cluster_id': cluster['id']}
),
jsonutils.dumps({
'title': title,
'description': description
}),
headers=self.default_headers,
expect_errors=True
)
self.assertEqual(resp.status_code, 400)
self.assertEqual(len(self.env.clusters[0].dashboard_entries), 0)

View File

@ -1,124 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2015 Mirantis, 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.
from nailgun.db.sqlalchemy.models.dashboard_entry import DashboardEntry
from nailgun.test.base import BaseIntegrationTest
from nailgun.utils import reverse
from oslo.serialization import jsonutils
class TestHandlers(BaseIntegrationTest):
def test_dashboard_entry_update(self):
cluster = self.env.create_cluster(api=False)
dashboard_entry = self.env \
.create_dashboard_entry(cluster_id=cluster.id)
dashboard_entry_update = {
'title': 'new title 2',
'description': 'new description 2'
}
resp = self.app.put(
reverse(
'DashboardEntryHandler',
kwargs={'cluster_id': cluster['id'],
'obj_id': dashboard_entry.id}
),
jsonutils.dumps(dashboard_entry_update),
headers=self.default_headers
)
self.assertEqual(dashboard_entry.id, resp.json_body['id'])
self.assertEqual('new title 2', resp.json_body['title'])
self.assertEqual('new description 2', resp.json_body['description'])
self.assertEqual(dashboard_entry.url, resp.json_body['url'])
def test_dashboard_entry_get_with_cluster(self):
cluster = self.env.create_cluster(api=False)
dashboard_entry = self.env \
.create_dashboard_entry(cluster_id=cluster.id)
resp = self.app.get(
reverse(
'DashboardEntryHandler',
kwargs={'cluster_id': cluster['id'],
'obj_id': dashboard_entry.id}
),
headers=self.default_headers
)
self.assertEqual(200, resp.status_code)
self.assertEqual(dashboard_entry.id, resp.json_body['id'])
self.assertEqual(dashboard_entry.title, resp.json_body['title'])
self.assertEqual(dashboard_entry.url, resp.json_body['url'])
self.assertEqual(dashboard_entry.description,
resp.json_body['description'])
def test_dashboard_entry_not_found(self):
cluster = self.env.create_cluster(api=False)
dashboard_entry = self.env \
.create_dashboard_entry(cluster_id=cluster.id)
resp = self.app.get(
reverse(
'DashboardEntryHandler',
kwargs={'cluster_id': cluster['id'],
'obj_id': dashboard_entry.id + 1}
),
headers=self.default_headers,
expect_errors=True
)
self.assertEqual(404, resp.status_code)
def test_dashboard_entry_delete(self):
cluster = self.env.create_cluster(api=False)
dashboard_entry = self.env \
.create_dashboard_entry(cluster_id=cluster.id)
resp = self.app.delete(
reverse(
'DashboardEntryHandler',
kwargs={'cluster_id': cluster['id'],
'obj_id': dashboard_entry.id}
),
headers=self.default_headers,
)
self.assertEqual(204, resp.status_code)
d_e_query = self.db.query(DashboardEntry) \
.filter_by(cluster_id=cluster.id)
self.assertEquals(d_e_query.count(), 0)
def test_dashboard_entry_patch(self):
cluster = self.env.create_cluster(api=False)
dashboard_entry = self.env \
.create_dashboard_entry(cluster_id=cluster.id)
dashboard_entry_update = {
'title': 'new title 3',
'description': 'new description 3'
}
resp = self.app.patch(
reverse(
'DashboardEntryHandler',
kwargs={'cluster_id': cluster['id'],
'obj_id': dashboard_entry.id}
),
jsonutils.dumps(dashboard_entry_update),
headers=self.default_headers
)
self.assertEqual(dashboard_entry.id, resp.json_body['id'])
self.assertEqual('new title 3', resp.json_body['title'])
self.assertEqual('new description 3', resp.json_body['description'])
self.assertEqual(dashboard_entry.url, resp.json_body['url'])

View File

@ -472,3 +472,21 @@ class TestMasterSettingsMigration(base.BaseAlembicMigrationTest):
bootstrap_settings,
jsonutils.loads(result.scalar())['bootstrap']
)
class TestClusterPluginLinks(base.BaseAlembicMigrationTest):
def test_cluster_plugin_links_creation(self):
clusters = self.meta.tables['clusters']
cluster_plugin_links = self.meta.tables['cluster_plugin_links']
cluster_id = db.execute(sa.select([clusters])).scalar()
db.execute(
cluster_plugin_links.insert(),
[{
'cluster_id': cluster_id,
'title': 'title',
'url': 'http://www.zzz.com',
'description': 'description',
'hidden': False
}])