Merge pull request #10600 from borgstrom/pyobjects_saltobject

Adding a object interface to __salt__ & __pillar__ (pyobjects)
This commit is contained in:
Thomas S Hatch 2014-02-20 10:17:35 -07:00
commit 7a3bf8aa85
3 changed files with 107 additions and 10 deletions

View File

@ -105,12 +105,49 @@ a state.
Service.running(Extend('apache'),
watch=[{'file': '/etc/httpd/extra/httpd-vhosts.conf'}])
Pillar data
^^^^^^^^^^^
Pyobjects provides a shortcut function for calling ``salt['pillar.get']`` that
helps maintain the readability of your state files. It can be accessed using
the ``Pillar`` object.
The following lines are functionally equivalent:
.. code-block:: python
:linenos:
#!pyobjects
value = Pillar('foo:bar:baz', 'qux')
value = salt['pillar.get']('foo:bar:baz', 'qux')
SaltObject
^^^^^^^^^^
In the spirit of the object interface for creating state data pyobjects also
provides a simple object interface to the ``__salt__`` object.
An object named ``Salt`` exists in scope for your sls files and will dispatch
its attributes to the ``__salt__`` dictionary.
The following lines are functionally equivalent:
.. code-block:: python
:linenos:
#!pyobjects
ret = Salt.cmd.run(bar)
ret = salt['cmd.run'](bar)
TODO
^^^^
* Interface for working with reactor files
'''
import logging
from salt.loader import states
from salt.utils.pyobjects import StateRegistry
from salt.utils.pyobjects import StateRegistry, SaltObject
from salt.utils.pyobjects import StateFactory # pylint: disable=W0611
# DO NOT REMOVE THE DISABLE ABOVE, it's used in an exec call below
@ -153,6 +190,12 @@ def render(template, saltenv='base', sls='',
pillar = __pillar__
grains = __grains__
salt = __salt__
# create our SaltObject
Salt = SaltObject(__salt__)
# add a Pillar shortcut
Pillar = __salt__['pillar.get']
except NameError:
pass

View File

@ -5,6 +5,8 @@
Pythonic object interface to creating state data, see the pyobjects renderer
for more documentation.
'''
from collections import namedtuple
from salt.utils.odict import OrderedDict
REQUISITES = ('require', 'watch', 'use', 'require_in', 'watch_in', 'use_in')
@ -228,3 +230,36 @@ class State(object):
def __exit__(self, type, value, traceback):
self.registry.pop_requisite()
class SaltObject(object):
'''
Object based interface to the functions in __salt__
.. code-block:: python
:linenos:
Salt = SaltObject(__salt__)
Salt.cmd.run(bar)
'''
def __init__(self, salt):
_mods = {}
for full_func in salt:
mod, func = full_func.split('.')
if mod not in _mods:
_mods[mod] = {}
_mods[mod][func] = salt[full_func]
# now transform using namedtuples
self.mods = {}
for mod in _mods:
mod_object = namedtuple('%sModule' % mod.capitalize(),
_mods[mod].keys())
self.mods[mod] = mod_object(**_mods[mod])
def __getattr__(self, mod):
if mod not in self.mods:
raise AttributeError
return self.mods[mod]

View File

@ -13,7 +13,7 @@ from salt.minion import SMinion
from salt.renderers.pyobjects import render as pyobjects_render
from salt.utils.odict import OrderedDict
from salt.utils.pyobjects import (StateFactory, State, StateRegistry,
InvalidFunction)
InvalidFunction, SaltObject)
test_registry = StateRegistry()
File = StateFactory('file', registry=test_registry)
@ -31,22 +31,22 @@ pydmesg_salt_expected = OrderedDict([('/usr/local/bin/pydmesg', pydmesg_expected
pydmesg_kwargs = dict(user='root', group='root', mode='0755',
source='salt://debian/files/pydmesg.py')
basic_template = """#!pyobjects
basic_template = '''#!pyobjects
File.directory('/tmp', mode='1777', owner='root', group='root')
"""
'''
invalid_template = """#!pyobjects
invalid_template = '''#!pyobjects
File.fail('/tmp')
"""
'''
include_template = """#!pyobjects
include_template = '''#!pyobjects
Include('http')
"""
'''
extend_template = """#!pyobjects
extend_template = '''#!pyobjects
Include('http')
Service.running(Extend('apache'), watch=[{'file': '/etc/file'}])
"""
'''
class StateTests(TestCase):
@ -163,3 +163,22 @@ class RendererTests(TestCase):
}),
])),
]))
class SaltObjectTests(TestCase):
def test_salt_object(self):
def attr_fail():
Salt.fail.blah()
def times2(x):
return x*2
__salt__ = {
'math.times2': times2
}
Salt = SaltObject(__salt__)
self.assertRaises(AttributeError, attr_fail)
self.assertEqual(Salt.math.times2, times2)
self.assertEqual(Salt.math.times2(2), 4)