saltstack/salt — pull request #12577 by jasonrm (2014-05-06 21:34:27+00:00)
Title: Make `salt_import` available to pyobjects rendered files

As I've been working through converting my jijna-heavy states to pyobjects states I've discovered that nested imports using the `salt://` syntax doesn't work. Looks like it's because it does a regex/load/exec for the initial pyobjects file it renders, but not included children.

One idea I tried was adding an object to `sys.meta_path` that had the `find_module` and `load_module` functions, however I couldn't get that to work correctly. It feels like it would have been cleaner than this solution which is to add yet another function `salt_import` into the pyobjects rendered global scope.

My greatly simplified example is below. If you switch the commenting on the salt\_import and from/import statements the from/import version should fail on the line `from salt://module/service/service_py.sls import SaltService`.

I'm not a python guy, so I just hack away until it works for me. If there is a cleaner way to handle nested imports I'd love to see it. The part I hate the most of this is the return syntax of `salt_import`. It feels ugly to pull the module I want out like that, but I don't know any better way.

How do you feel about this @borgstrom?

ps. My apologies for not writing/updating tests, they are something I've had trouble with getting to run in the past and just haven't had a chance to get them running right again. My python-newbness is also a major factor.

#### top.sls
```yaml
base:
'*':
- role.developer
```

#### role/developer.sls
```yaml
#!pyobjects

PerconaInstance = salt_import('salt://module/percona/instance_py.sls')['PerconaInstance']
# from salt://module/percona/instance_py.sls import PerconaInstance

instance = PerconaInstance()
with instance.present():
Event.fire_master('percona/ready', data={})
```

#### module/percona/instance_py.sls
```yaml
#!pyobjects

SaltService = salt_import('salt://module/service/service_py.sls')['SaltService']
# from salt://module/service/service_py.sls import SaltService

class PerconaInstance:

def present(self):
# Why do I have to do global here? It looks like it should be in scope.
global SaltService
service = SaltService()
with service.present():
return Event.fire_master('percona/instance', data={})
```

#### module/service/service_py.sls
```yaml
#!pyobjects

class SaltService():

def present(self):
return Event.fire_master('service/present', data={})
```