mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-09 10:41:31 -07:00
This is an exceedingly rough sketch of what attributes might look like - metaclass implementations NOT complete.
This commit is contained in:
parent
0c40c6c23c
commit
335221d79e
8 changed files with 128 additions and 63 deletions
2
Makefile
2
Makefile
|
@ -94,7 +94,7 @@ tests:
|
||||||
PYTHONPATH=./lib $(NOSETESTS) -d -w test/units -v
|
PYTHONPATH=./lib $(NOSETESTS) -d -w test/units -v
|
||||||
|
|
||||||
newtests:
|
newtests:
|
||||||
PYTHONPATH=./v2/ $(NOSETESTS) -d -w v2/tests -v
|
PYTHONPATH=./v2 $(NOSETESTS) -d -w test/v2 -v
|
||||||
|
|
||||||
|
|
||||||
authors:
|
authors:
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit cb69744bcee4b4217d83b4a30006635ba69e2aa0
|
Subproject commit f624689bad24cb3a7b2ef43d5280b5f4fbabb5bd
|
2
test/v2/playbook/__init__.py
Normal file
2
test/v2/playbook/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# TODO: header
|
||||||
|
|
37
test/v2/playbook/task.py
Normal file
37
test/v2/playbook/task.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# TODO: header
|
||||||
|
|
||||||
|
from ansible.playbook.task import Task
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
basic_shell_task = dict(
|
||||||
|
name = 'Test Task',
|
||||||
|
shell = 'echo hi'
|
||||||
|
)
|
||||||
|
|
||||||
|
class TestTask(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_can_construct_empty_task():
|
||||||
|
t = Task()
|
||||||
|
|
||||||
|
def test_can_construct_task_with_role():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_can_construct_task_with_block():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_can_construct_task_with_role_and_block():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_can_load_simple_task():
|
||||||
|
t = Task.load(basic_shell_task)
|
||||||
|
assert t.name == basic_shell_task['name']
|
||||||
|
assert t.module == 'shell'
|
||||||
|
assert t.args == 'echo hi'
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import ansible.utils
|
|
||||||
|
|
||||||
class Playbook(object):
|
class Playbook(object):
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
self.ds = v2.utils.load_yaml_from_file(filename)
|
self.ds = v2.utils.load_yaml_from_file(filename)
|
||||||
|
|
|
@ -15,11 +15,23 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from errors import AnsibleError
|
#from ansible.cmmon.errors import AnsibleError
|
||||||
from playbook.tag import Tag
|
#from playbook.tag import Tag
|
||||||
|
|
||||||
class Base(object):
|
class Base(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, attribute):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add_attribute(self):
|
||||||
|
self.attributes.push(attribute)
|
||||||
|
|
||||||
|
def load(self, data):
|
||||||
|
for attribute in self.attributes:
|
||||||
|
attribute.load(data)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
for attribute in self.attributes:
|
||||||
|
attribute.validate(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from playbook.base import Base
|
from ansible.playbook.base import Base
|
||||||
from playbook.conditional import Conditional
|
from ansible.playbook.attribute import Attribute, FieldAttribute
|
||||||
from errors import AnsibleError
|
from ansible.playbook.conditional import Conditional
|
||||||
from ansible import utils
|
#from ansible.common.errors import AnsibleError
|
||||||
|
#from ansible import utils
|
||||||
|
|
||||||
# TODO: it would be fantastic (if possible) if a task new where in the YAML it was defined for describing
|
# TODO: it would be fantastic (if possible) if a task new where in the YAML it was defined for describing
|
||||||
# it in error conditions
|
# it in error conditions
|
||||||
|
@ -36,81 +37,94 @@ class Task(Base):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# =================================================================================
|
# =================================================================================
|
||||||
# KEYS AND SLOTS: defines what variables in are valid in the data structure and
|
# ATTRIBUTES
|
||||||
# the object itself
|
# load_<attribute_name> and
|
||||||
|
# validate_<attribute_name>
|
||||||
|
# will be used if defined
|
||||||
|
# might be possible to define others
|
||||||
|
|
||||||
VALID_KEYS = [
|
always_run = FieldAttribute(isa='bool')
|
||||||
'always_run', 'any_errors_fatal', 'async', 'connection', 'delay', 'delegate_to', 'environment',
|
any_errors_fatal = FieldAttribute(isa='bool')
|
||||||
'first_available_file', 'ignore_errors', 'include', 'local_action', 'meta', 'name', 'no_log',
|
async = FieldAttribute(isa='int')
|
||||||
'notify', 'poll', 'register', 'remote_user', 'retries', 'run_once', 'su', 'su_pass', 'su_user',
|
connection = FieldAttribute(isa='string')
|
||||||
'sudo', 'sudo_pass', 'sudo_user', 'transport', 'until'
|
delay = FieldAttribute(isa='int')
|
||||||
]
|
delegate_to = FieldAttribute(isa='string')
|
||||||
|
environment = FieldAttribute(isa='dict')
|
||||||
|
first_available_file = FieldAttribute(isa='list')
|
||||||
|
ignore_errors = FieldAttribute(isa='bool')
|
||||||
|
|
||||||
__slots__ = [
|
# FIXME: this should not be a Task
|
||||||
'_always_run', '_any_errors_fatal', '_async', '_connection', '_delay', '_delegate_to', '_environment',
|
# include = FieldAttribute(isa='string')
|
||||||
'_first_available_file', '_ignore_errors', '_include', '_local_action', '_meta', '_name', '_no_log',
|
|
||||||
'_notify', '_poll', '_register', '_remote_user', '_retries', '_run_once', '_su', '_su_pass', '_su_user',
|
local_action = FieldAttribute(isa='string', alias='action', post_validate='_set_local_action')
|
||||||
'_sudo', '_sudo_pass', '_sudo_user', '_transport', '_until'
|
|
||||||
]
|
# FIXME: this should not be a Task
|
||||||
|
meta = FieldAttribute(isa='string')
|
||||||
|
|
||||||
|
name = FieldAttribute(isa='string', post_validate='_set_name')
|
||||||
|
no_log = FieldAttribute(isa='bool')
|
||||||
|
notify = FieldAttribute(isa='list')
|
||||||
|
poll = FieldAttribute(isa='integer')
|
||||||
|
register = FieldAttribute(isa='string')
|
||||||
|
remote_user = FieldAttribute(isa='string')
|
||||||
|
retries = FieldAttribute(isa='integer')
|
||||||
|
run_once = FieldAttribute(isa='bool')
|
||||||
|
su = FieldAttribute(isa='bool')
|
||||||
|
su_pass = FieldAttribute(isa='string')
|
||||||
|
su_user = FieldAttribute(isa='string')
|
||||||
|
sudo = FieldAttribute(isa='bool')
|
||||||
|
sudo_user = FieldAttribute(isa='string')
|
||||||
|
sudo_pass = FieldAttribute(isa='string')
|
||||||
|
transport = FieldAttribute(isa='string')
|
||||||
|
until = FieldAttribute(isa='list') # ?
|
||||||
|
|
||||||
|
role = 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
|
||||||
self._reset()
|
|
||||||
super(Task, self).__init__()
|
super(Task, self).__init__()
|
||||||
|
|
||||||
# TODO: move to BaseObject
|
|
||||||
def _reset(self):
|
|
||||||
''' clear out the object '''
|
|
||||||
|
|
||||||
for x in __slots__:
|
|
||||||
setattr(x, None)
|
|
||||||
|
|
||||||
# ==================================================================================
|
# ==================================================================================
|
||||||
# BASIC ACCESSORS
|
# 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:
|
if self._role:
|
||||||
return "%s : %s" % (self._role.get_name(), self._name)
|
return "%s : %s" % (self._role.get_name(), self._name)
|
||||||
else:
|
else:
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
# FIXME: does a task have variables?
|
@classmethod
|
||||||
def get_vars(self):
|
def load(self, block=None, role=None, data=None):
|
||||||
''' return the variables associated with the task '''
|
self = Task(block=block, role=role)
|
||||||
raise exception.NotImplementedError()
|
self._load_field_attributes(data) # from BaseObject
|
||||||
|
self._load_plugin_attributes(data) # from here, becuase of lookupPlugins
|
||||||
|
return self
|
||||||
|
|
||||||
def get_role(self):
|
def _load_plugin_attributes(self, data):
|
||||||
''' return the role associated with the task '''
|
module_names = self._module_names()
|
||||||
return self._role
|
for (k,v) in data.iteritems():
|
||||||
|
if k in module_names:
|
||||||
def get_block(self):
|
self.module = k
|
||||||
''' return the block the task is in '''
|
self.args = v
|
||||||
return self._block
|
|
||||||
|
|
||||||
|
|
||||||
# ==================================================================================
|
# ==================================================================================
|
||||||
# LOAD: functions related to walking the datastructure and storing data
|
# BELOW THIS LINE
|
||||||
|
# info below this line is "old" and is before the attempt to build Attributes
|
||||||
|
# use as reference but plan to replace and radically simplify
|
||||||
|
# ==================================================================================
|
||||||
|
|
||||||
def _load_parameters(data):
|
LEGACY = """
|
||||||
''' validate/transmogrify/assign any module parameters for this task '''
|
|
||||||
|
|
||||||
if isinstance(data, dict):
|
|
||||||
return dict(_parameters=data)
|
|
||||||
elif isinstance(data, basestring):
|
|
||||||
return dict(_parameters=utils.parse_kv(data))
|
|
||||||
elif isinstance(data, None):
|
|
||||||
return dict(_parameters='')
|
|
||||||
else:
|
|
||||||
raise AnsibleError("invalid arguments specified, got '%s' (type=%s')" % (data, type(data)))
|
|
||||||
|
|
||||||
def _load_action(self, ds, k, v):
|
def _load_action(self, ds, k, v):
|
||||||
''' validate/transmogrify/assign the module and parameters if used in 'action/local_action' format '''
|
''' validate/transmogrify/assign the module and parameters if used in 'action/local_action' format '''
|
||||||
|
@ -301,3 +315,5 @@ class Task(Base):
|
||||||
if self._first_available_file and self._lookup_plugin:
|
if self._first_available_file and self._lookup_plugin:
|
||||||
raise AnsibleError("with_(plugin), and first_available_file are mutually incompatible in a single task")
|
raise AnsibleError("with_(plugin), and first_available_file are mutually incompatible in a single task")
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from v2.inventory import Host
|
#from v2.inventory import Host
|
||||||
from v2.playbook import Task
|
#from v2.playbook import Task
|
||||||
|
|
||||||
class Runner(object):
|
class Runner(object):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue