1""" 2Pure python state renderer 3========================== 4 5To use this renderer, the SLS file should contain a function called ``run`` 6which returns highstate data. 7 8The highstate data is a dictionary containing identifiers as keys, and execution 9dictionaries as values. For example the following state declaration in YAML: 10 11.. code-block:: yaml 12 13 common_packages: 14 pkg.installed: 15 - pkgs: 16 - curl 17 - vim 18 19translates to: 20 21.. code-block:: python 22 23 {'common_packages': {'pkg.installed': [{'pkgs': ['curl', 'vim']}]}} 24 25In this module, a few objects are defined for you, giving access to Salt's 26execution functions, grains, pillar, etc. They are: 27 28- ``__salt__`` - :ref:`Execution functions <all-salt.modules>` (i.e. 29 ``__salt__['test.echo']('foo')``) 30- ``__grains__`` - :ref:`Grains <targeting-grains>` (i.e. ``__grains__['os']``) 31- ``__pillar__`` - :ref:`Pillar data <pillar>` (i.e. ``__pillar__['foo']``) 32- ``__opts__`` - Minion configuration options 33- ``__env__`` - The effective salt fileserver environment (i.e. ``base``). Also 34 referred to as a "saltenv". ``__env__`` should not be modified in a pure 35 python SLS file. To use a different environment, the environment should be 36 set when executing the state. This can be done in a couple different ways: 37 38 - Using the ``saltenv`` argument on the salt CLI (i.e. ``salt '*' state.sls 39 foo.bar.baz saltenv=env_name``). 40 - By adding a ``saltenv`` argument to an individual state within the SLS 41 file. In other words, adding a line like this to the state's data 42 structure: ``{'saltenv': 'env_name'}`` 43 44- ``__sls__`` - The SLS path of the file. For example, if the root of the base 45 environment is ``/srv/salt``, and the SLS file is 46 ``/srv/salt/foo/bar/baz.sls``, then ``__sls__`` in that file will be 47 ``foo.bar.baz``. 48 49When writing a reactor SLS file the global context ``data`` (same as context ``{{ data }}`` 50for states written with Jinja + YAML) is available. The following YAML + Jinja state declaration: 51 52.. code-block:: jinja 53 54 {% if data['id'] == 'mysql1' %} 55 highstate_run: 56 local.state.apply: 57 - tgt: mysql1 58 {% endif %} 59 60translates to: 61 62.. code-block:: python 63 64 if data['id'] == 'mysql1': 65 return {'highstate_run': {'local.state.apply': [{'tgt': 'mysql1'}]}} 66 67Full Example 68------------ 69 70.. code-block:: python 71 :linenos: 72 73 #!py 74 75 def run(): 76 config = {} 77 78 if __grains__['os'] == 'Ubuntu': 79 user = 'ubuntu' 80 group = 'ubuntu' 81 home = '/home/{0}'.format(user) 82 else: 83 user = 'root' 84 group = 'root' 85 home = '/root/' 86 87 config['s3cmd'] = { 88 'pkg': [ 89 'installed', 90 {'name': 's3cmd'}, 91 ], 92 } 93 94 config[home + '/.s3cfg'] = { 95 'file.managed': [ 96 {'source': 'salt://s3cfg/templates/s3cfg'}, 97 {'template': 'jinja'}, 98 {'user': user}, 99 {'group': group}, 100 {'mode': 600}, 101 {'context': { 102 'aws_key': __pillar__['AWS_ACCESS_KEY_ID'], 103 'aws_secret_key': __pillar__['AWS_SECRET_ACCESS_KEY'], 104 }, 105 }, 106 ], 107 } 108 109 return config 110 111""" 112 113import os 114 115import salt.utils.templates 116from salt.exceptions import SaltRenderError 117 118 119def render(template, saltenv="base", sls="", tmplpath=None, **kws): 120 """ 121 Render the python module's components 122 123 :rtype: string 124 """ 125 template = tmplpath 126 if not os.path.isfile(template): 127 raise SaltRenderError("Template {} is not a file!".format(template)) 128 129 tmp_data = salt.utils.templates.py( 130 template, 131 True, 132 __salt__=__salt__, 133 salt=__salt__, 134 __grains__=__grains__, 135 grains=__grains__, 136 __opts__=__opts__, 137 opts=__opts__, 138 __pillar__=__pillar__, 139 pillar=__pillar__, 140 __env__=saltenv, 141 saltenv=saltenv, 142 __sls__=sls, 143 sls=sls, 144 **kws 145 ) 146 if not tmp_data.get("result", False): 147 raise SaltRenderError( 148 tmp_data.get("data", "Unknown render error in py renderer") 149 ) 150 151 return tmp_data["data"] 152