WIP on Attributes. Getting closer.

This commit is contained in:
Michael DeHaan 2014-10-03 16:37:32 -04:00
parent b02afa2268
commit b54434c1b2
5 changed files with 71 additions and 49 deletions

View file

@ -16,20 +16,22 @@ class TestTask(unittest.TestCase):
def tearDown(self):
pass
def test_can_construct_empty_task():
def test_can_construct_empty_task(self):
t = Task()
def test_can_construct_task_with_role():
def test_can_construct_task_with_role(self):
pass
def test_can_construct_task_with_block():
def test_can_construct_task_with_block(self):
pass
def test_can_construct_task_with_role_and_block():
def test_can_construct_task_with_role_and_block(self):
pass
def test_can_load_simple_task():
def test_can_load_simple_task(self):
t = Task.load(basic_shell_task)
assert t is not None
print "T.NAME = %s" % t.name
assert t.name == basic_shell_task['name']
assert t.module == 'shell'
assert t.args == 'echo hi'

View file

@ -23,6 +23,7 @@ class Attribute(object):
self.isa = isa
self.validator = validator
self.post_validator = post_validator
self.value = None
class FieldAttribute(Attribute):

View file

@ -17,21 +17,51 @@
#from ansible.cmmon.errors import AnsibleError
#from playbook.tag import Tag
from ansible.playbook.attribute import Attribute, FieldAttribute
class Base(object):
def __init__(self, attribute):
pass
def __init__(self):
self._data = dict()
self._attributes = dict()
def add_attribute(self):
self.attributes.push(attribute)
def load_data(self, ds):
''' walk the input datastructure and assign any values '''
def load(self, data):
for attribute in self.attributes:
attribute.load(data)
assert ds is not None
for name in self.__class__.__dict__:
print "DEBUG: processing attribute: %s" % name
attribute = self.__class__.__dict__[name]
if isinstance(attribute, FieldAttribute):
method = getattr(self, '_load_%s' % name, None)
if method:
self._attributes[name] = method(self, attribute)
else:
if name in ds:
self._attributes[name] = ds[name]
# implement PluginAtrribute which allows "with_" and "action" aliases.
return self
def attribute_value(self, name):
return self._attributes[name]
def validate(self):
for attribute in self.attributes:
attribute.validate(self)
for name in self.__dict__:
attribute = self.__dict__[name]
if instanceof(attribute, FieldAttribute):
method = getattr(self, '_validate_%s' % (prefix, name), None)
if method:
method(self, attribute)
def post_validate(self, runner_context):
raise exception.NotImplementedError
# TODO: __getattr__ that looks inside _attributes

View file

@ -20,9 +20,14 @@ from v2.utils import list_union
class Role(PlaybookBase):
# TODO: this will be overhauled to match Task.py at some point
def __init__(self):
pass
def get_name(self):
return "TEMPORARY"
def load(self, ds):
self._ds = ds
self._tasks = []

View file

@ -43,6 +43,7 @@ class Task(Base):
# will be used if defined
# might be possible to define others
action = FieldAttribute(isa='string')
always_run = FieldAttribute(isa='bool')
any_errors_fatal = FieldAttribute(isa='bool')
async = FieldAttribute(isa='int')
@ -54,14 +55,14 @@ class Task(Base):
ignore_errors = FieldAttribute(isa='bool')
# FIXME: this should not be a Task
# include = FieldAttribute(isa='string')
# include = FieldAttribute(isa='string')
local_action = FieldAttribute(isa='string', alias='action', post_validate='_set_local_action')
local_action = FieldAttribute(isa='string')
# FIXME: this should not be a Task
meta = FieldAttribute(isa='string')
name = FieldAttribute(isa='string', validate=self._set_name)
name = FieldAttribute(isa='string')
no_log = FieldAttribute(isa='bool')
notify = FieldAttribute(isa='list')
@ -82,29 +83,33 @@ class Task(Base):
role = Attribute()
block = Attribute()
# ==================================================================================
def __init__(self, block=None, role=None):
''' constructors a task, without the Task.load classmethod, it will be pretty blank '''
self.block = block
self.role = role
self._block = block
self._role = role
super(Task, self).__init__()
# ==================================================================================
# BASIC ACCESSORS
def get_name(self):
''' return the name of the task '''
if self._role:
return "%s : %s" % (self._role.get_name(), self._name)
# FIXME: getattr magic in baseclass so this is not required:
original = self.attribute_value('name')
role_value = self.attribute_value('role')
if role_value:
return "%s : %s" % (role_value.get_name(), original)
else:
return self._name
return original
@staticmethod
def load(data, block=block, role=role):
t = Task(block=block, role=role)
return t.load_data(data)
def __repr__(self):
''' returns a human readable representation of the task '''
return "TASK: %s" % self.get_name()
# ==================================================================================
# BELOW THIS LINE
# info below this line is "old" and is before the attempt to build Attributes
@ -237,27 +242,6 @@ LEGACY = """
else:
return self._load_other_valid_key
@classmethod
def load(self, ds, block=None, role=None):
''' walk the datastructure and store/validate parameters '''
self = Task(block=block, role=role)
return self._load_from_datastructure(ds)
# TODO: move to BaseObject
def _load_from_datastructure(ds)
self._pre_validate(ds)
# load the keys from the datastructure
for k,v in ds.iteritems():
mods = self._loader_for_key(k)(k,v)
if (k,v) in mods.iteritems():
setattr(self,k,v)
self._post_validate()
return self
# ==================================================================================
# PRE-VALIDATION - expected to be uncommonly used, this checks for arguments that
# are aliases of each other. Most everything else should be in the LOAD block