Implementation of the OCCI v1.1 Core Model
Set of classes that represent the OCCI Core Model as described in the GFD.183 – OCCI Core (v1.1) [1], along with some unit tests for the model. [1] http://ogf.org/documents/GFD.183.pdf
This commit is contained in:
parent
68d53fdbd0
commit
414e0c3fbe
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 ooi.occi.core import category
|
||||
|
||||
|
||||
class Action(category.Category):
|
||||
"""OCCI Action.
|
||||
|
||||
An Action represents an invocable operation applicable to a resource
|
||||
instance.
|
||||
"""
|
||||
pass
|
|
@ -0,0 +1,48 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 abc
|
||||
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Attribute(object):
|
||||
def __init__(self, name, value):
|
||||
self._name = name
|
||||
self._value = value
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self._value
|
||||
|
||||
|
||||
class MutableAttribute(Attribute):
|
||||
@Attribute.value.setter
|
||||
def value(self, value):
|
||||
self._value = value
|
||||
|
||||
|
||||
class InmutableAttribute(Attribute):
|
||||
pass
|
||||
|
||||
|
||||
class AttributeCollection(object):
|
||||
pass
|
|
@ -0,0 +1,52 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 ooi.occi.core import attribute
|
||||
from ooi.occi import helpers
|
||||
|
||||
|
||||
class Category(object):
|
||||
"""OCCI Category."""
|
||||
|
||||
def __init__(self, scheme, term, title, attributes=[], location=None):
|
||||
self._scheme = scheme
|
||||
self._term = term
|
||||
self._title = title
|
||||
|
||||
helpers.check_type(attributes, attribute.Attribute)
|
||||
|
||||
self._attributes = dict([(a.name, a) for a in attributes])
|
||||
self._location = location
|
||||
|
||||
@property
|
||||
def scheme(self):
|
||||
return self._scheme
|
||||
|
||||
@property
|
||||
def term(self):
|
||||
return self._term
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
return self._title
|
||||
|
||||
@property
|
||||
def attributes(self):
|
||||
return self._attributes
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
return self._location
|
|
@ -0,0 +1,65 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 abc
|
||||
|
||||
import six
|
||||
|
||||
from ooi.occi import helpers
|
||||
from ooi.occi.core import attribute
|
||||
from ooi.occi.core import kind
|
||||
from ooi.occi.core import mixin
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Entity(object):
|
||||
"""OCCI Entity.
|
||||
|
||||
Entity is an abstract type, which both Resource and Link inherit. Each
|
||||
sub-type of Entity is identified by a unique Kind instance
|
||||
"""
|
||||
|
||||
def __init__(self, id, title, mixins):
|
||||
helpers.check_type(mixins, mixin.Mixin)
|
||||
self.mixins = mixins
|
||||
|
||||
self._attributes = {
|
||||
"occi.core.id": attribute.InmutableAttribute("occi.core.id", id),
|
||||
"occi.core.title": attribute.MutableAttribute("occi.core.title", title)
|
||||
}
|
||||
|
||||
self._kind = kind.Kind(helpers.build_schema('core'), 'entity', 'entity',
|
||||
self._attributes.values(), '/entity/')
|
||||
|
||||
@property
|
||||
def kind(self):
|
||||
return self._kind
|
||||
|
||||
@property
|
||||
def attributes(self):
|
||||
return self._attributes
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._attributes["occi.core.id"].value
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
return self._attributes["occi.core.title"].value
|
||||
|
||||
@title.setter
|
||||
def title(self, value):
|
||||
self._attributes["occi.core.title"].value = value
|
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 ooi.occi.core import action
|
||||
from ooi.occi.core import category
|
||||
from ooi.occi import helpers
|
||||
|
||||
|
||||
class Kind(category.Category):
|
||||
"""OCCI Kind.
|
||||
|
||||
The Kind type is the core of the type classification system built into the
|
||||
OCCI Core Model. Kind is a specialisation of Category and introduces
|
||||
additional resource capabilities in terms of Actions.
|
||||
"""
|
||||
|
||||
def __init__(self, scheme, term, title, attributes=[], location=None,
|
||||
related=[], actions=[]):
|
||||
super(Kind, self).__init__(scheme, term, title, attributes=attributes,
|
||||
location=location)
|
||||
|
||||
helpers.check_type(related, Kind)
|
||||
helpers.check_type(actions, action.Action)
|
||||
|
||||
self.related = related
|
||||
self.actions = actions
|
|
@ -0,0 +1,56 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 ooi.occi import helpers
|
||||
from ooi.occi.core import attribute
|
||||
from ooi.occi.core import entity
|
||||
from ooi.occi.core import kind
|
||||
|
||||
|
||||
class Link(entity.Entity):
|
||||
"""OCCI Resoure.
|
||||
|
||||
The Resource type is complemented by the Link type which associates one
|
||||
Resource instance with another.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, id, title, mixins, source, target):
|
||||
super(Link, self).__init__(id, title, mixins)
|
||||
|
||||
cls_attrs = {
|
||||
"occi.core.source": attribute.MutableAttribute("occi.core.source", source),
|
||||
"occi.core.target": attribute.MutableAttribute("occi.core.target", target),
|
||||
}
|
||||
self._attributes.update(cls_attrs)
|
||||
self._kind = kind.Kind(helpers.build_schema("core"), 'link', 'link', self._attributes.values(), '/link/')
|
||||
|
||||
@property
|
||||
def source(self):
|
||||
return self._attributes["occi.core.source"].value
|
||||
|
||||
@source.setter
|
||||
def source(self, value):
|
||||
self._attributes["occi.core.source"].value = value
|
||||
|
||||
@property
|
||||
def target(self):
|
||||
return self._attributes["occi.core.target"].value
|
||||
|
||||
@target.setter
|
||||
def target(self, value):
|
||||
self._attributes["occi.core.target"].value = value
|
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 ooi.occi.core import action
|
||||
from ooi.occi.core import category
|
||||
from ooi.occi import helpers
|
||||
|
||||
|
||||
class Mixin(category.Category):
|
||||
"""OCCI Mixin.
|
||||
|
||||
An instance of Mixin can be associated with a resource instance, i.e. a
|
||||
sub-type of Entity, to "mix-in" additional resource capabilities at
|
||||
run-time.
|
||||
"""
|
||||
|
||||
def __init__(self, scheme, term, title, attributes=[], location=None,
|
||||
related=[], actions=[]):
|
||||
super(Mixin, self).__init__(scheme, term, title, attributes=attributes,
|
||||
location=location)
|
||||
|
||||
helpers.check_type(related, Mixin)
|
||||
helpers.check_type(actions, action.Action)
|
||||
|
||||
self.related = related
|
||||
self.actions = actions
|
|
@ -0,0 +1,65 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
from ooi.occi import helpers
|
||||
from ooi.occi.core import attribute
|
||||
from ooi.occi.core import entity
|
||||
from ooi.occi.core import kind
|
||||
from ooi.occi.core import link
|
||||
|
||||
class Resource(entity.Entity):
|
||||
"""OCCI Resource.
|
||||
|
||||
The heart of the OCCI Core Model is the Resource type. Any resource exposed
|
||||
through OCCI is a Resource or a sub-type thereof. A resource can be e.g. a
|
||||
virtual machine, a job in a job submission system, a user, etc.
|
||||
|
||||
The Resource type is complemented by the Link type which associates one
|
||||
Resource instance with another. The Link type contains a number of common
|
||||
attributes that Link sub-types inherit.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, id, title, mixins, summary):
|
||||
super(Resource, self).__init__(id, title, mixins)
|
||||
|
||||
cls_attrs = {
|
||||
"occi.core.summary": attribute.MutableAttribute("occi.core.summary", summary),
|
||||
}
|
||||
self._attributes.update(cls_attrs)
|
||||
|
||||
self._kind = kind.Kind(helpers.build_schema('core'), 'resource', 'resource',
|
||||
self._attributes.values(), '/resource/')
|
||||
|
||||
self._links = []
|
||||
|
||||
@property
|
||||
def links(self):
|
||||
return self._links
|
||||
|
||||
def link(self, target, mixins=[]):
|
||||
l = link.Link(uuid.uuid4().hex, "", mixins, self, target)
|
||||
self._links.append(l)
|
||||
|
||||
@property
|
||||
def summary(self):
|
||||
return self._attributes["occi.core.summary"].value
|
||||
|
||||
@summary.setter
|
||||
def summary(self, value):
|
||||
self._attributes["occi.core.summary"].value = value
|
|
@ -0,0 +1,32 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 urlparse
|
||||
|
||||
_PREFIX = "http://schemas.ogf.org/occi/"
|
||||
|
||||
|
||||
def build_schema(category):
|
||||
category = "%s#" % category
|
||||
return urlparse.urljoin(_PREFIX, category)
|
||||
|
||||
|
||||
def check_type(obj_list, obj_type):
|
||||
if not isinstance(obj_list, list):
|
||||
raise TypeError('must be a list of objects')
|
||||
|
||||
if not all([isinstance(i, obj_type) for i in obj_list]):
|
||||
raise TypeError('object must be of class %s' % obj_type)
|
|
@ -0,0 +1,247 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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 ooi.occi.core import action
|
||||
from ooi.occi.core import attribute
|
||||
from ooi.occi.core import category
|
||||
from ooi.occi.core import entity
|
||||
from ooi.occi.core import kind
|
||||
from ooi.occi.core import link
|
||||
from ooi.occi.core import mixin
|
||||
from ooi.occi.core import resource
|
||||
from ooi.tests import base
|
||||
|
||||
|
||||
class TestAttributes(base.TestCase):
|
||||
def test_base(self):
|
||||
attr = attribute.Attribute("occi.foo.bar", "crap")
|
||||
self.assertEqual("crap", attr.value)
|
||||
|
||||
def test_mutable(self):
|
||||
attr = attribute.MutableAttribute("occi.foo.bar", "crap")
|
||||
attr.value = "bazonk"
|
||||
self.assertEqual("bazonk", attr.value)
|
||||
|
||||
def test_inmutable(self):
|
||||
attr = attribute.InmutableAttribute("occi.foo.bar", "crap")
|
||||
|
||||
def set_val():
|
||||
attr.value = "bazonk"
|
||||
|
||||
self.assertRaises(AttributeError, set_val)
|
||||
|
||||
|
||||
class TestCoreOCCICategory(base.TestCase):
|
||||
args = ("scheme", "term", "title")
|
||||
obj = category.Category
|
||||
|
||||
def test_obj(self):
|
||||
cat = self.obj(*self.args)
|
||||
|
||||
for i in self.args:
|
||||
self.assertEqual(i, getattr(cat, i))
|
||||
|
||||
def test_attributes(self):
|
||||
attr = attribute.MutableAttribute("occi.foo.bar", "crap")
|
||||
cat = self.obj(*self.args, attributes=[attr])
|
||||
self.assertEqual({"occi.foo.bar": attr}, cat.attributes)
|
||||
|
||||
def test_attributes_empty(self):
|
||||
cat = self.obj(*self.args, attributes=[])
|
||||
self.assertEqual({}, cat.attributes)
|
||||
|
||||
def test_attributes_invalid(self):
|
||||
self.assertRaises(TypeError,
|
||||
self.obj,
|
||||
*self.args,
|
||||
attributes=None)
|
||||
|
||||
def test_attributes_invalid_list(self):
|
||||
self.assertRaises(TypeError,
|
||||
self.obj,
|
||||
*self.args,
|
||||
attributes=[None])
|
||||
|
||||
|
||||
class TestCoreOCCIKind(TestCoreOCCICategory):
|
||||
obj = kind.Kind
|
||||
|
||||
def setUp(self):
|
||||
super(TestCoreOCCIKind, self).setUp()
|
||||
|
||||
def test_obj(self):
|
||||
k = self.obj(*self.args)
|
||||
for i in (self.args):
|
||||
self.assertEqual(i, getattr(k, i))
|
||||
|
||||
def test_actions(self):
|
||||
actions = [action.Action(None, None, None)]
|
||||
kind = self.obj(*self.args, actions=actions)
|
||||
|
||||
for i in (self.args):
|
||||
self.assertEqual(i, getattr(kind, i))
|
||||
self.assertEqual(actions, kind.actions)
|
||||
|
||||
def test_actions_empty(self):
|
||||
actions = []
|
||||
kind = self.obj(*self.args, actions=actions)
|
||||
|
||||
for i in (self.args):
|
||||
self.assertEqual(i, getattr(kind, i))
|
||||
self.assertEqual(actions, kind.actions)
|
||||
|
||||
def test_actions_invalid(self):
|
||||
actions = None
|
||||
self.assertRaises(TypeError,
|
||||
self.obj,
|
||||
*self.args,
|
||||
actions=actions)
|
||||
|
||||
def test_actions_invalid_list(self):
|
||||
actions = [None]
|
||||
self.assertRaises(TypeError,
|
||||
self.obj,
|
||||
*self.args,
|
||||
actions=actions)
|
||||
|
||||
def test_related(self):
|
||||
related = [self.obj(None, None, None)]
|
||||
kind = self.obj(*self.args, related=related)
|
||||
|
||||
for i in (self.args):
|
||||
self.assertEqual(i, getattr(kind, i))
|
||||
self.assertEqual(related, kind.related)
|
||||
|
||||
def test_related_empty(self):
|
||||
related = []
|
||||
kind = self.obj(*self.args, related=related)
|
||||
|
||||
for i in (self.args):
|
||||
self.assertEqual(i, getattr(kind, i))
|
||||
self.assertEqual(related, kind.related)
|
||||
|
||||
def test_related_invalid(self):
|
||||
related = None
|
||||
self.assertRaises(TypeError,
|
||||
self.obj,
|
||||
*self.args,
|
||||
related=related)
|
||||
|
||||
def test_related_invalid_list(self):
|
||||
related = [None]
|
||||
self.assertRaises(TypeError,
|
||||
self.obj,
|
||||
*self.args,
|
||||
related=related)
|
||||
|
||||
|
||||
class TestCoreOCCIMixin(TestCoreOCCIKind):
|
||||
obj = mixin.Mixin
|
||||
|
||||
|
||||
class TestCoreOCCIAction(TestCoreOCCICategory):
|
||||
obj = action.Action
|
||||
|
||||
|
||||
class TestCoreOCCIEntity(base.TestCase):
|
||||
def test_entity(self):
|
||||
e = entity.Entity("foo", "bar", [])
|
||||
self.assertIsInstance(e.kind, kind.Kind)
|
||||
self.assertIn("occi.core.id", e.attributes)
|
||||
self.assertIn("occi.core.title", e.attributes)
|
||||
|
||||
self.assertEqual("foo", e.attributes["occi.core.id"].value)
|
||||
self.assertEqual("foo", e.id)
|
||||
self.assertIs(e.id, e.attributes["occi.core.id"].value)
|
||||
|
||||
def set_attr():
|
||||
e.attributes["occi.core.id"].value = "foo"
|
||||
self.assertRaises(AttributeError, set_attr)
|
||||
|
||||
def set_attr_directly():
|
||||
e.id = "foo"
|
||||
self.assertRaises(AttributeError, set_attr_directly)
|
||||
|
||||
e.title = "baz"
|
||||
self.assertEqual("baz", e.attributes["occi.core.title"].value)
|
||||
self.assertEqual("baz", e.title)
|
||||
self.assertIs(e.title, e.attributes["occi.core.title"].value)
|
||||
|
||||
e.attributes["occi.core.title"].value = "bar"
|
||||
self.assertEqual("bar", e.attributes["occi.core.title"].value)
|
||||
self.assertEqual("bar", e.title)
|
||||
self.assertIs(e.title, e.attributes["occi.core.title"].value)
|
||||
|
||||
|
||||
class TestCoreOCCIResource(base.TestCase):
|
||||
def test_resource(self):
|
||||
r = resource.Resource("foo", "bar", [], "baz")
|
||||
self.assertIsInstance(r.kind, kind.Kind)
|
||||
self.assertEqual("resource", r.kind.term)
|
||||
self.assertEqual("foo", r.id)
|
||||
self.assertEqual("bar", r.title)
|
||||
self.assertEqual("baz", r.summary)
|
||||
r.summary = "bazonk"
|
||||
self.assertEqual("bazonk", r.summary)
|
||||
|
||||
def test_valid_link(self):
|
||||
r1 = resource.Resource(None, None, [], None)
|
||||
r2 = resource.Resource(None, None, [], None)
|
||||
r1.link(r2)
|
||||
self.assertIsInstance(r1.links[0], link.Link)
|
||||
self.assertIs(r1, r1.links[0].source)
|
||||
self.assertIs(r2, r1.links[0].target)
|
||||
|
||||
def test_mixins(self):
|
||||
m = mixin.Mixin(None, None, None)
|
||||
r = resource.Resource(None, None, [m], [])
|
||||
self.assertIsInstance(r.kind, kind.Kind)
|
||||
self.assertEqual([m], r.mixins)
|
||||
|
||||
def test_invalid_mixins(self):
|
||||
self.assertRaises(TypeError,
|
||||
resource.Resource,
|
||||
None, None, ["foo"], None)
|
||||
|
||||
|
||||
class TestCoreOCCILink(base.TestCase):
|
||||
def test_correct_link(self):
|
||||
resource_1 = resource.Resource(None, None, [], None)
|
||||
resource_2 = resource.Resource(None, None, [], None)
|
||||
resource_3 = resource.Resource(None, None, [], None)
|
||||
l = link.Link(None, None, [], resource_1, resource_2)
|
||||
self.assertIsInstance(l.kind, kind.Kind)
|
||||
self.assertEqual("link", l.kind.term)
|
||||
self.assertIs(resource_1, l.source)
|
||||
self.assertIs(resource_2, l.target)
|
||||
|
||||
self.assertIs(resource_1, l.attributes["occi.core.source"].value)
|
||||
self.assertIs(resource_1, l.source)
|
||||
self.assertIs(resource_1, l.attributes["occi.core.source"].value)
|
||||
|
||||
self.assertIs(resource_2, l.attributes["occi.core.target"].value)
|
||||
self.assertIs(resource_2, l.target)
|
||||
self.assertIs(resource_2, l.attributes["occi.core.target"].value)
|
||||
|
||||
l.source = resource_3
|
||||
self.assertIs(resource_3, l.attributes["occi.core.source"].value)
|
||||
self.assertIs(resource_3, l.source)
|
||||
self.assertIs(resource_3, l.attributes["occi.core.source"].value)
|
||||
|
||||
l.target = resource_1
|
||||
self.assertIs(resource_1, l.target)
|
||||
self.assertIs(resource_1, l.attributes["occi.core.target"].value)
|
||||
self.assertIs(resource_1, l.attributes["occi.core.target"].value)
|
Loading…
Reference in New Issue