@ -445,6 +445,7 @@ class JinjaPluginIntercept(MutableMapping):
# FUTURE: we can cache FQ filter/test calls for the entire duration of a run, since a given collection's impl's
# aren't supposed to change during a run
def __getitem__ ( self , key ) :
original_key = key
self . _load_ansible_plugins ( )
try :
@ -459,56 +460,61 @@ class JinjaPluginIntercept(MutableMapping):
if func :
return func
# didn't find it in the pre-built Jinja env, assume it's a former builtin and follow the normal routing path
leaf_key = key
key = ' ansible.builtin. ' + key
else :
leaf_key = key . split ( ' . ' ) [ - 1 ]
key , leaf_key = get_fqcr_and_name ( key )
seen = set ( )
while True :
if key in seen :
raise TemplateSyntaxError (
' recursive collection redirect found for %r ' % original_key ,
0
)
seen . add ( key )
acr = AnsibleCollectionRef . try_parse_fqcr ( key , self . _dirname )
acr = AnsibleCollectionRef . try_parse_fqcr ( key , self . _dirname )
if not acr :
raise KeyError ( ' invalid plugin name: {0} ' . format ( key ) )
if not acr :
raise KeyError ( ' invalid plugin name: {0} ' . format ( key ) )
ts = _get_collection_metadata ( acr . collection )
ts = _get_collection_metadata ( acr . collection )
# TODO: implement support for collection-backed redirect (currently only builtin)
# TODO: implement cycle detection (unified across collection redir as well)
# TODO: implement cycle detection (unified across collection redir as well)
routing_entry = ts . get ( ' plugin_routing ' , { } ) . get ( self . _dirname , { } ) . get ( leaf_key , { } )
routing_entry = ts . get ( ' plugin_routing ' , { } ) . get ( self . _dirname , { } ) . get ( leaf_key , { } )
deprecation_entry = routing_entry . get ( ' deprecation ' )
if deprecation_entry :
warning_text = deprecation_entry . get ( ' warning_text ' )
removal_date = deprecation_entry . get ( ' removal_date ' )
removal_version = deprecation_entry . get ( ' removal_version ' )
deprecation_entry = routing_entry . get ( ' deprecation ' )
if deprecation_entry :
warning_text = deprecation_entry . get ( ' warning_text ' )
removal_date = deprecation_entry . get ( ' removal_date ' )
removal_version = deprecation_entry . get ( ' removal_version ' )
if not warning_text :
warning_text = ' {0} " {1} " is deprecated ' . format ( self . _dirname , key )
if not warning_text :
warning_text = ' {0} " {1} " is deprecated ' . format ( self . _dirname , key )
display . deprecated ( warning_text , version = removal_version , date = removal_date , collection_name = acr . collection )
display . deprecated ( warning_text , version = removal_version , date = removal_date , collection_name = acr . collection )
tombstone_entry = routing_entry . get ( ' tombstone ' )
tombstone_entry = routing_entry . get ( ' tombstone ' )
if tombstone_entry :
warning_text = tombstone_entry . get ( ' warning_text ' )
removal_date = tombstone_entry . get ( ' removal_date ' )
removal_version = tombstone_entry . get ( ' removal_version ' )
if tombstone_entry :
warning_text = tombstone_entry . get ( ' warning_text ' )
removal_date = tombstone_entry . get ( ' removal_date ' )
removal_version = tombstone_entry . get ( ' removal_version ' )
if not warning_text :
warning_text = ' {0} " {1} " has been removed ' . format ( self . _dirname , key )
if not warning_text :
warning_text = ' {0} " {1} " has been removed ' . format ( self . _dirname , key )
exc_msg = display . get_deprecation_message ( warning_text , version = removal_version , date = removal_date ,
collection_name = acr . collection , removed = True )
exc_msg = display . get_deprecation_message ( warning_text , version = removal_version , date = removal_date ,
collection_name = acr . collection , removed = True )
raise AnsiblePluginRemovedError ( exc_msg )
raise AnsiblePluginRemovedError ( exc_msg )
redirect_fqcr = routing_entry . get ( ' redirect ' , None )
if redirect_fqcr :
acr = AnsibleCollectionRef . from_fqcr ( ref = redirect_fqcr , ref_type = self . _dirname )
display . vvv ( ' redirecting {0} {1} to {2} . {3} ' . format ( self . _dirname , key , acr . collection , acr . resource ) )
key = redirect_fqcr
# TODO: handle recursive forwarding (not necessary for builtin, but definitely for further collection redirs)
redirect = routing_entry . get ( ' redirect ' , None )
if redirect :
next_key , leaf_key = get_fqcr_and_name ( redirect , collection = acr . collection )
display . vvv ( ' redirecting (type: {0} ) {1} . {2} to {3} ' . format ( self . _dirname , acr . collection , acr . resource , next_key ) )
key = next_key
else :
break
func = self . _collection_jinja_func_cache . get ( key )
@ -576,6 +582,17 @@ class JinjaPluginIntercept(MutableMapping):
return len ( self . _delegatee )
def get_fqcr_and_name ( resource , collection = ' ansible.builtin ' ) :
if ' . ' not in resource :
name = resource
fqcr = collection + ' . ' + resource
else :
name = resource . split ( ' . ' ) [ - 1 ]
fqcr = resource
return fqcr , name
class AnsibleEnvironment ( Environment ) :
'''
Our custom environment , which simply allows us to override the class - level