mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
WIP on Attributes. Getting closer.
This commit is contained in:
parent
b02afa2268
commit
b54434c1b2
5 changed files with 71 additions and 49 deletions
|
@ -16,20 +16,22 @@ class TestTask(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_can_construct_empty_task():
|
def test_can_construct_empty_task(self):
|
||||||
t = Task()
|
t = Task()
|
||||||
|
|
||||||
def test_can_construct_task_with_role():
|
def test_can_construct_task_with_role(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_can_construct_task_with_block():
|
def test_can_construct_task_with_block(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_can_construct_task_with_role_and_block():
|
def test_can_construct_task_with_role_and_block(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_can_load_simple_task():
|
def test_can_load_simple_task(self):
|
||||||
t = Task.load(basic_shell_task)
|
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.name == basic_shell_task['name']
|
||||||
assert t.module == 'shell'
|
assert t.module == 'shell'
|
||||||
assert t.args == 'echo hi'
|
assert t.args == 'echo hi'
|
||||||
|
|
|
@ -23,6 +23,7 @@ class Attribute(object):
|
||||||
self.isa = isa
|
self.isa = isa
|
||||||
self.validator = validator
|
self.validator = validator
|
||||||
self.post_validator = post_validator
|
self.post_validator = post_validator
|
||||||
|
self.value = None
|
||||||
|
|
||||||
class FieldAttribute(Attribute):
|
class FieldAttribute(Attribute):
|
||||||
|
|
||||||
|
|
|
@ -17,21 +17,51 @@
|
||||||
|
|
||||||
#from ansible.cmmon.errors import AnsibleError
|
#from ansible.cmmon.errors import AnsibleError
|
||||||
#from playbook.tag import Tag
|
#from playbook.tag import Tag
|
||||||
|
from ansible.playbook.attribute import Attribute, FieldAttribute
|
||||||
|
|
||||||
class Base(object):
|
class Base(object):
|
||||||
|
|
||||||
def __init__(self, attribute):
|
def __init__(self):
|
||||||
pass
|
self._data = dict()
|
||||||
|
self._attributes = dict()
|
||||||
|
|
||||||
def add_attribute(self):
|
def load_data(self, ds):
|
||||||
self.attributes.push(attribute)
|
''' walk the input datastructure and assign any values '''
|
||||||
|
|
||||||
def load(self, data):
|
assert ds is not None
|
||||||
for attribute in self.attributes:
|
|
||||||
attribute.load(data)
|
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):
|
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
|
||||||
|
|
|
@ -20,9 +20,14 @@ from v2.utils import list_union
|
||||||
|
|
||||||
class Role(PlaybookBase):
|
class Role(PlaybookBase):
|
||||||
|
|
||||||
|
# TODO: this will be overhauled to match Task.py at some point
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return "TEMPORARY"
|
||||||
|
|
||||||
def load(self, ds):
|
def load(self, ds):
|
||||||
self._ds = ds
|
self._ds = ds
|
||||||
self._tasks = []
|
self._tasks = []
|
||||||
|
|
|
@ -43,6 +43,7 @@ class Task(Base):
|
||||||
# will be used if defined
|
# will be used if defined
|
||||||
# might be possible to define others
|
# might be possible to define others
|
||||||
|
|
||||||
|
action = FieldAttribute(isa='string')
|
||||||
always_run = FieldAttribute(isa='bool')
|
always_run = FieldAttribute(isa='bool')
|
||||||
any_errors_fatal = FieldAttribute(isa='bool')
|
any_errors_fatal = FieldAttribute(isa='bool')
|
||||||
async = FieldAttribute(isa='int')
|
async = FieldAttribute(isa='int')
|
||||||
|
@ -54,14 +55,14 @@ class Task(Base):
|
||||||
ignore_errors = FieldAttribute(isa='bool')
|
ignore_errors = FieldAttribute(isa='bool')
|
||||||
|
|
||||||
# FIXME: this should not be a Task
|
# 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
|
# FIXME: this should not be a Task
|
||||||
meta = FieldAttribute(isa='string')
|
meta = FieldAttribute(isa='string')
|
||||||
|
|
||||||
name = FieldAttribute(isa='string', validate=self._set_name)
|
name = FieldAttribute(isa='string')
|
||||||
|
|
||||||
no_log = FieldAttribute(isa='bool')
|
no_log = FieldAttribute(isa='bool')
|
||||||
notify = FieldAttribute(isa='list')
|
notify = FieldAttribute(isa='list')
|
||||||
|
@ -82,29 +83,33 @@ class Task(Base):
|
||||||
role = Attribute()
|
role = Attribute()
|
||||||
block = Attribute()
|
block = Attribute()
|
||||||
|
|
||||||
# ==================================================================================
|
|
||||||
|
|
||||||
def __init__(self, block=None, role=None):
|
def __init__(self, block=None, role=None):
|
||||||
''' constructors a task, without the Task.load classmethod, it will be pretty blank '''
|
''' constructors a task, without the Task.load classmethod, it will be pretty blank '''
|
||||||
self.block = block
|
self._block = block
|
||||||
self.role = role
|
self._role = role
|
||||||
super(Task, self).__init__()
|
super(Task, self).__init__()
|
||||||
|
|
||||||
# ==================================================================================
|
|
||||||
# BASIC ACCESSORS
|
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
''' return the name of the task '''
|
''' 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:
|
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):
|
def __repr__(self):
|
||||||
''' returns a human readable representation of the task '''
|
''' returns a human readable representation of the task '''
|
||||||
return "TASK: %s" % self.get_name()
|
return "TASK: %s" % self.get_name()
|
||||||
|
|
||||||
|
|
||||||
# ==================================================================================
|
# ==================================================================================
|
||||||
# BELOW THIS LINE
|
# BELOW THIS LINE
|
||||||
# info below this line is "old" and is before the attempt to build Attributes
|
# info below this line is "old" and is before the attempt to build Attributes
|
||||||
|
@ -237,27 +242,6 @@ LEGACY = """
|
||||||
else:
|
else:
|
||||||
return self._load_other_valid_key
|
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
|
# 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
|
# are aliases of each other. Most everything else should be in the LOAD block
|
||||||
|
|
Loading…
Reference in a new issue