Designing Models¶
General Guidelines¶
In general, any object that is represented in the MiQ Appliance is going to be only relevant along with the context of a particular appliance. The objects in the codebase are designed to function similarly to REST API based objects where you have a Collection object that handles the creation/searching/non-instance functions, and then an Entity object that handles the particular instance usage.
Arguments¶
A collection object must take an appliance as its first argument. This is to ensure that
- any objects created with the collection will have the correct context and
- that there is a consistent API for collection objects.
An entity object must take a collection as its first argument. This is to ensure that
- the entity can access an appliance through its collecion and
- that there is a consistent API for collection objects
Warning
Objects should never be instantiated directly. They should always come from a collection.
Collection Methods¶
__init__()
- The collection object must take anappliance
argument as its first argument and assign this to theself.appliance
attribute.instantiate()
- The collection object should provide aninstantiate()
method which will simply return an entity instance with the supplied arguments. It must passself
as the first argument so that the user doesn’t have to.create()
- The collection object should provider acreate()
method where appropriate. This method will attempt to create the object on the appliance and must then callself.instantiate
and return the object.
Note
The __init__()
method could in the future become part automatic in the BaseCollection class
but this is a future feature and is not yet planned.
Warning
Failure to comply with the above guidelines in the future may result in an Exception being raised
Entity Methods¶
__init__()
- The entity object must take acollection
argument as its first argument and assign this to theself.collection
attribute. It must then assignself.appliance
to be equal toself.collection.appliance
Note
The __init__()
method could in the future become part automatic in the BaseEntity class
but this is a future feature and is not yet planned.
Warning
Failure to comply with the above guidelines in the future may result in an Exception being raised
Example¶
Below is an example of a generic object using the collection and entity relationships
from cfme.utils.appliance import BaseCollection, BaseEntity
class ObjectCollection(BaseCollection):
"""An object collection"""
def __init__(self, appliance):
self.appliance = appliance
def instantiate(self, name, label):
return Object(self, name, label)
def create(self, name, label):
run_create(name, label)
return self.instantiate(name, label)
class Object(BaseEntity):
"""An object entity"""
def __init__(self, collection, name, label):
self.collection = collection
self.appliance = self.collection.appliance
def update(self, *updates):
some_update_mechanism(*updates)
An example of the models usage in testing is described below
from some.model import ObjectCollection
def test_something_good(appliance):
"""A test for something good"""
oc = ObjectCollection(appliance)
ob = oc.create('ObName', 'ObLabel')
ob.update({'label': 'Edited'})