[CORD-2080] Adding 'tosca_key' support in xproto
Change-Id: Ib01c1cdcb81a51819c9e08703e6c76a4ffa09f17
diff --git a/test/test_grpc_models_accessor.py b/test/test_grpc_models_accessor.py
index 3851857..729fac3 100644
--- a/test/test_grpc_models_accessor.py
+++ b/test/test_grpc_models_accessor.py
@@ -18,6 +18,7 @@
from mock import patch, MagicMock
from grpc_client.models_accessor import GRPCModelsAccessor
from grpc_client.resources import RESOURCES
+from grpc_client.KEYS import TOSCA_KEYS
class FakeObj:
new = None
@@ -34,15 +35,26 @@
mock_resources = {
'username~pass': {
- 'test-model': FakeResource
+ 'test-model': FakeResource,
+ 'single-key': FakeResource,
+ 'double-key': FakeResource
}
}
+mock_keys = {
+ 'i-do-not-exists': ['name'],
+ 'test-model': ['name'],
+ 'empty-key': [],
+ 'single-key': ['fake_key'],
+ 'double-key': ['key_1', 'key_2'],
+}
+
USERNAME = 'username'
PASSWORD = 'pass'
class GRPCModelsAccessor_Create_or_update_Test(unittest.TestCase):
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
def test_unkown_user(self):
"""
[GRPCModelsAccessor] get_model_from_classname: If a user does not have orm classes, raise
@@ -55,6 +67,7 @@
self.assertEqual(e.exception.message, "[XOS-TOSCA] User 'username' does not have ready resources")
@patch.dict(RESOURCES, mock_resources, clear=True)
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
def test_unkown_module(self):
"""
[GRPCModelsAccessor] get_model_from_classname: If a model is not know by the grpc api, raise
@@ -64,35 +77,92 @@
}
with self.assertRaises(Exception) as e:
GRPCModelsAccessor.get_model_from_classname('i-do-not-exists', data, USERNAME, PASSWORD)
- self.assertEqual(e.exception.message, "[XOS-TOSCA] The model you are trying to create (name: test, class: i-do-not-exists) is not know by xos-core")
+ self.assertEqual(e.exception.message, "[XOS-TOSCA] The model you are trying to create (class: i-do-not-exists, properties, {'name': 'test'}) is not know by xos-core")
+
+ def test_unkown_tosca_key(self):
+ """
+ [GRPCModelsAccessor] get_model_from_classname: If a model does not have a tosca_key, raise
+ """
+ data = {
+ "name": "test"
+ }
+ with self.assertRaises(Exception) as e:
+ GRPCModelsAccessor.get_model_from_classname('no-key', data, USERNAME, PASSWORD)
+ self.assertEqual(e.exception.message, "[XOS-TOSCA] Model no-key doesn't have a tosca_key specified")
+
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
+ def test_empty_tosca_key(self):
+ """
+ [GRPCModelsAccessor] get_model_from_classname: If a model does not have a tosca_key, raise
+ """
+ data = {
+ "name": "test"
+ }
+ with self.assertRaises(Exception) as e:
+ GRPCModelsAccessor.get_model_from_classname('empty-key', data, USERNAME, PASSWORD)
+ self.assertEqual(e.exception.message, "[XOS-TOSCA] Model empty-key doesn't have a tosca_key specified")
+
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
+ def test_tosca_key_are_defined(self):
+ """
+ [GRPCModelsAccessor] get_model_from_classname: a model should have a property for it's tosca_key
+ """
+ data = {
+ "name": "test",
+ }
+ with self.assertRaises(Exception) as e:
+ GRPCModelsAccessor.get_model_from_classname('single-key', data, USERNAME, PASSWORD)
+ self.assertEqual(e.exception.message, "[XOS-TOSCA] Model single-key doesn't have a property for the specified tosca_key ('fake_key')")
@patch.object(FakeResource.objects, "filter")
@patch.object(FakeResource.objects, "new", MagicMock(return_value=FakeModel))
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
+ def test_composite_key(self, mock_filter):
+ """
+ [GRPCModelsAccessor] get_model_from_classname: should use a composite key to lookup a model
+ """
+ data = {
+ "name": "test",
+ "key_1": "key1",
+ "key_2": "key2"
+ }
+ with patch.dict(RESOURCES, mock_resources, clear=True):
+ model = GRPCModelsAccessor.get_model_from_classname('double-key', data, USERNAME, PASSWORD)
+ mock_filter.assert_called_with(key_1="key1", key_2="key2")
+ self.assertEqual(model, FakeModel)
+
+ @patch.object(FakeResource.objects, "filter")
+ @patch.object(FakeResource.objects, "new", MagicMock(return_value=FakeModel))
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
def test_new_model(self, mock_filter):
"""
[GRPCModelsAccessor] get_model_from_classname: should create a new model
"""
data = {
- "name": "test"
+ "name": "test",
+ "fake_key": "key"
}
with patch.dict(RESOURCES, mock_resources, clear=True):
- model = GRPCModelsAccessor.get_model_from_classname('test-model', data, USERNAME, PASSWORD)
- mock_filter.assert_called_with(name="test")
+ model = GRPCModelsAccessor.get_model_from_classname('single-key', data, USERNAME, PASSWORD)
+ mock_filter.assert_called_with(fake_key="key")
self.assertEqual(model, FakeModel)
@patch.object(FakeResource.objects, "filter", MagicMock(return_value=[FakeExistingModel]))
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
def test_existing_model(self):
"""
[GRPCModelsAccessor] get_model_from_classname: should update an existing model
"""
data = {
- "name": "test"
+ "name": "test",
+ "fake_key": "key"
}
with patch.dict(RESOURCES, mock_resources, clear=True):
- model = GRPCModelsAccessor.get_model_from_classname('test-model', data, USERNAME, PASSWORD)
+ model = GRPCModelsAccessor.get_model_from_classname('single-key', data, USERNAME, PASSWORD)
self.assertEqual(model, FakeExistingModel)
@patch.object(FakeResource.objects, "filter", MagicMock(return_value=['a', 'b']))
+ @patch.dict(TOSCA_KEYS, mock_keys, clear=True)
def test_multiple_models(self):
"""
[GRPCModelsAccessor] get_model_from_classname: should raise an exception if multiple instances are found
@@ -103,33 +173,7 @@
with patch.dict(RESOURCES, mock_resources, clear=True):
with self.assertRaises(Exception) as e:
GRPCModelsAccessor.get_model_from_classname('test-model', data, USERNAME, PASSWORD)
- self.assertEqual(e.exception.message, "[XOS-Tosca] Model test has multiple instances, I can't handle it")
-
- @patch.dict(RESOURCES, mock_resources, clear=True)
- @patch.object(FakeResource.objects, "filter")
- @patch.object(FakeResource.objects, "new")
- def test_find_model_without_name_property(self, mock_new, mock_filter):
- """
- [GRPCModelsAccessor] get_model_from_classname: should lookup a model by the first property
- """
- data = {
- 'foo': 'bar',
- 'something': 'else'
- }
- GRPCModelsAccessor.get_model_from_classname('test-model', data, USERNAME, PASSWORD)
- mock_filter.assert_called_with(foo="bar")
- mock_new.assert_called()
-
- @patch.dict(RESOURCES, mock_resources, clear=True)
- @patch.object(FakeResource.objects, "new")
- def test_model_without_properties(self, mock_new):
- """
- [GRPCModelsAccessor] get_model_from_classname: should create a new model if not properties are specified
- """
- data = {
- }
- GRPCModelsAccessor.get_model_from_classname('test-model', data, USERNAME, PASSWORD)
- mock_new.assert_called()
+ self.assertEqual(e.exception.message, "[XOS-Tosca] Model of class test-model and properties {'name': 'test'} has multiple instances, I can't handle it")
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
diff --git a/test/test_tosca_parser_e2e.py b/test/test_tosca_parser_e2e.py
index a4c8e29..87f3cf1 100644
--- a/test/test_tosca_parser_e2e.py
+++ b/test/test_tosca_parser_e2e.py
@@ -220,4 +220,4 @@
with self.assertRaises(Exception) as e:
parser.execute()
- self.assertEqual(e.exception.message.message, "[XOS-TOSCA] Model Site:Open Networking Lab has property 'must-exist' but cannot be found")
+ self.assertEqual(e.exception.message.message, "[XOS-TOSCA] Model of class Site and properties {'name': 'Open Networking Lab'} has property 'must-exist' but cannot be found")
diff --git a/test/tosca/link.yaml b/test/tosca/link.yaml
new file mode 100644
index 0000000..f2c000f
--- /dev/null
+++ b/test/tosca/link.yaml
@@ -0,0 +1,160 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Persist xos-sample-gui-extension
+
+imports:
+ - custom_types/slice.yaml
+ - custom_types/network.yaml
+ - custom_types/networkslice.yaml
+ - custom_types/networktemplate.yaml
+ - custom_types/site.yaml
+ - custom_types/image.yaml
+ - custom_types/service.yaml
+ - custom_types/serviceinstance.yaml
+ - custom_types/serviceinstancelink.yaml
+
+topology_template:
+ node_templates:
+
+ service#mcord:
+ type: tosca.nodes.Service
+ properties:
+ name: mcord
+
+ test1:
+ type: tosca.nodes.ServiceInstance
+ properties:
+ name: test1
+
+ test2:
+ type: tosca.nodes.ServiceInstance
+ properties:
+ name: test2
+
+ link1:
+ type: tosca.nodes.ServiceInstanceLink
+ requirements:
+ - provider_service_instance:
+ node: test1
+ relationship: tosca.relationships.BelongsToOne
+ - subscriber_service_instance:
+ node: test2
+ relationship: tosca.relationships.BelongsToOne
+
+ link2:
+ type: tosca.nodes.ServiceInstanceLink
+ requirements:
+ - subscriber_service:
+ node: service#mcord
+ relationship: tosca.relationships.BelongsToOne
+ - provider_service_instance:
+ node: test2
+ relationship: tosca.relationships.BelongsToOne
+
+ # Site
+ mysite:
+ type: tosca.nodes.Site
+ properties:
+ must-exist: true
+ name: mysite
+
+ # Images
+ image#trusty-server-multi-nic:
+ type: tosca.nodes.Image
+ properties:
+ must-exist: true
+ name: trusty-server-multi-nic
+
+ # slices
+ slice#slice1:
+ type: tosca.nodes.Slice
+ properties:
+ name: mysite_slice1
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.BelongsToOne
+ - default_image:
+ node: image#trusty-server-multi-nic
+ relationship: tosca.relationships.BelongsToOne
+
+ slice#slice2:
+ type: tosca.nodes.Slice
+ properties:
+ name: mysite_slice2
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.BelongsToOne
+ - default_image:
+ node: image#trusty-server-multi-nic
+ relationship: tosca.relationships.BelongsToOne
+
+ # networks
+
+ shared_template:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ must-exist: true
+ name: shared_template
+
+ network#network1:
+ type: tosca.nodes.Network
+ properties:
+ name: network1
+ requirements:
+ - template:
+ node: shared_template
+ relationship: tosca.relationships.BelongsToOne
+ - owner:
+ node: slice#slice1
+ relationship: tosca.relationships.BelongsToOne
+
+ network#network2:
+ type: tosca.nodes.Network
+ properties:
+ name: network2
+ requirements:
+ - template:
+ node: shared_template
+ relationship: tosca.relationships.BelongsToOne
+ - owner:
+ node: slice#slice2
+ relationship: tosca.relationships.BelongsToOne
+
+ networkslice#slice1_network2:
+ type: tosca.nodes.NetworkSlice
+ requirements:
+ - network:
+ node: network#network2
+ relationship: tosca.relationships.BelongsToOne
+ - slice:
+ node: slice#slice1
+ relationship: tosca.relationships.BelongsToOne
+
+ networkslice#slice2_network1:
+ type: tosca.nodes.NetworkSlice
+ requirements:
+ - network:
+ node: network#network1
+ relationship: tosca.relationships.BelongsToOne
+ - slice:
+ node: slice#slice2
+ relationship: tosca.relationships.BelongsToOne
+