diff --git a/test/v2/playbook/test_task.py b/test/v2/playbook/test_task.py index 9f65a35cc5d..171b7128ea3 100644 --- a/test/v2/playbook/test_task.py +++ b/test/v2/playbook/test_task.py @@ -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' diff --git a/v2/ansible/playbook/attribute.py b/v2/ansible/playbook/attribute.py index b064406af7b..8b3dda88944 100644 --- a/v2/ansible/playbook/attribute.py +++ b/v2/ansible/playbook/attribute.py @@ -23,6 +23,7 @@ class Attribute(object): self.isa = isa self.validator = validator self.post_validator = post_validator + self.value = None class FieldAttribute(Attribute): diff --git a/v2/ansible/playbook/base.py b/v2/ansible/playbook/base.py index 8bc9a83bd32..f4b4d0819ee 100644 --- a/v2/ansible/playbook/base.py +++ b/v2/ansible/playbook/base.py @@ -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 diff --git a/v2/ansible/playbook/role.py b/v2/ansible/playbook/role.py index 0dd8817dbc9..dd1426ee8ae 100644 --- a/v2/ansible/playbook/role.py +++ b/v2/ansible/playbook/role.py @@ -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 = [] diff --git a/v2/ansible/playbook/task.py b/v2/ansible/playbook/task.py index 6c7d93f9fd4..24f2f8b432b 100644 --- a/v2/ansible/playbook/task.py +++ b/v2/ansible/playbook/task.py @@ -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