@@ -1444,7 +1444,7 @@ def load_dynamic(self, matches):
1444
1444
faux = {'state' : 'file' , 'fun' : 'recurse' }
1445
1445
self .state .module_refresh (faux )
1446
1446
1447
- def render_state (self , sls , env , mods ):
1447
+ def render_state (self , sls , env , mods , matches ):
1448
1448
'''
1449
1449
Render a state file and retrieve all of the include states
1450
1450
'''
@@ -1475,21 +1475,58 @@ def render_state(self, sls, env, mods):
1475
1475
errors .append (err )
1476
1476
else :
1477
1477
for inc_sls in state .pop ('include' ):
1478
- if fnmatch .filter (self .avail [env ], inc_sls ):
1478
+ # inc_sls may take the form of:
1479
+ # 'sls.to.include' <- same as {<env>: 'sls.to.include'}
1480
+ # {<env_key>: 'sls.to.include'}
1481
+ # {'_xenv': 'sls.to.resolve'}
1482
+ XENV_KEY = '_xenv'
1483
+
1484
+ if isinstance (inc_sls , dict ):
1485
+ env_key , inc_sls = inc_sls .popitem ()
1486
+ else :
1487
+ env_key = env
1488
+
1489
+ if env_key != XENV_KEY :
1490
+ # Resolve inc_sls in the specified environment
1491
+ if env_key in matches and fnmatch .filter (self .avail [env_key ], inc_sls ):
1492
+ resolved_envs = [env_key ]
1493
+ else :
1494
+ resolved_envs = []
1495
+ else :
1496
+ # Resolve inc_sls in the subset of environment matches
1497
+ resolved_envs = [
1498
+ aenv for aenv in matches
1499
+ if fnmatch .filter (self .avail [aenv ], inc_sls )
1500
+ ]
1501
+
1502
+ # An include must be resolved to a single environment, or
1503
+ # the include must exist in the current environment
1504
+ if len (resolved_envs ) == 1 or env in resolved_envs :
1479
1505
if inc_sls not in mods :
1480
1506
nstate , mods , err = self .render_state (
1481
- inc_sls ,
1482
- env ,
1483
- mods
1484
- )
1507
+ inc_sls ,
1508
+ resolved_envs [0 ] if len (resolved_envs ) == 1 else env ,
1509
+ mods ,
1510
+ matches
1511
+ )
1485
1512
if nstate :
1486
1513
state .update (nstate )
1487
1514
if err :
1488
1515
errors += err
1489
1516
else :
1490
- msg = ('Specified SLS {0} in environment {1} '
1491
- 'is not available on the salt master'
1492
- ).format (inc_sls , env )
1517
+ msg = ''
1518
+ if not resolved_envs :
1519
+ msg = ('Unknown include: Specified SLS {0}: {1} is not available on the salt '
1520
+ 'master in environment(s): {2} '
1521
+ ).format (env_key ,
1522
+ inc_sls ,
1523
+ ', ' .join (matches ) if env_key == XENV_KEY else env_key )
1524
+ elif len (resolved_envs ) > 1 :
1525
+ msg = ('Ambiguous include: Specified SLS {0}: {1} is available on the salt master '
1526
+ 'in multiple available environments: {2}'
1527
+ ).format (env_key ,
1528
+ inc_sls ,
1529
+ ', ' .join (resolved_envs ))
1493
1530
log .error (msg )
1494
1531
if self .opts ['failhard' ]:
1495
1532
errors .append (msg )
@@ -1595,7 +1632,7 @@ def render_highstate(self, matches):
1595
1632
mods = set ()
1596
1633
for sls_match in states :
1597
1634
for sls in fnmatch .filter (self .avail [env ], sls_match ):
1598
- state , mods , err = self .render_state (sls , env , mods )
1635
+ state , mods , err = self .render_state (sls , env , mods , matches )
1599
1636
# The extend members can not be treated as globally unique:
1600
1637
if '__extend__' in state and '__extend__' in highstate :
1601
1638
highstate ['__extend__' ].extend (state .pop ('__extend__' ))
0 commit comments