a )g2s@stddlmZmZmZeZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z ddlmZddlmZddlmZmZmZddlmZddlmZdd lmZmZdd lmZdd l m!Z!dd l"m#Z#dd l$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+e'Z,gdZ-ddej.DZ/ddej0DZ1e 2d3e-e/e1Z4e 2de j5Z6ddZ7ddZ8Gddde9Z:dS))absolute_importdivisionprint_functionN) attrgetter)shuffle) constants) AnsibleErrorAnsibleOptionsErrorAnsibleParserError) InventoryData) string_types)to_bytesto_text) parse_address)inventory_loader)deduplicate_list) unfrackpath)Display) combine_vars)get_vars_from_inventory_sources)s^\.s ^host_vars$s ^group_vars$s^vars_plugins$cCsg|] }t|qS)r .0xrr=/usr/lib/python3.9/site-packages/ansible/inventory/manager.py 0rcCsg|]}dtt|qS)s%s$)r reescaperrrrr1r|a>^ (.+) # A pattern expression ending with... \[(?: # A [subscript] expression comprising: (-?[0-9]+)| # A single positive or negative number ([0-9]+)([:-]) # Or an x:y or x: range. ([0-9]*) )\] $ cCspg}g}g}|D]D}|sq|ddkr2||q|ddkrJ||q||q|gkrddg}|||S)zS takes a list of patterns and reorders them by modifier to apply them consistently r!&all)append)patternsZpattern_regularZpattern_intersectionZpattern_excludeprrrorder_patternsBs     r&cCst|tr(dd|D}ttj|St|ts>t|dd}d|vrR|d}nBzt|dd\}}|g}Wn&t yt td|t j }Yn0d d |DS) a Takes a string containing host patterns separated by commas (or a list thereof) and returns a list of single patterns (which may not contain commas). Whitespace is ignored. Also accepts ':' as a separator for backwards compatibility, but it is not recommended due to the conflict with IPv6 addresses and host ranges. Example: 'a,b[1], c[2:3] , d' -> ['a', 'b[1]', 'c[2:3]', 'd'] css|]}t|VqdSN)split_host_patternrr%rrr krz%split_host_pattern..surrogate_or_stricterrors,T)Z allow_rangesaJ(?: # We want to match something comprising: [^\s:\[\]] # (anything other than whitespace or ':[]' | # ...or... \[[^\]]*\] # a single complete bracketed expression) )+ # occurring once or more cSsg|]}|r|qSr)stripr)rrrrrz&split_host_pattern..) isinstancelist itertoolschain from_iterabler rsplitr ExceptionrfindallX)patternresultsr$baseportrrrr(^s       r(c@seZdZdZd@ddZeddZedd Zed d ZdAd d Z ddZ ddZ ddZ ddZ ddZdBddZdCddZddZdd Zd!d"ZdDd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/ZdEd0d1Zd2d3Zd4d5Zd6d7Zd8d9Zd:d;Zdd?Z!dS)FInventoryManagerz Creates and manages inventory NTcCsp||_t|_d|_d|_i|_i|_|dur6g|_nt|t rJ|g|_n||_|r`|j |dg|_ g|_ dS)Ncache) _loaderr _inventory _restriction_subset_hosts_patterns_cache_pattern_cache_sourcesr0r parse_sources_cached_dynamic_hosts_cached_dynamic_grouping)selfloaderZsourcesparser?rrr__init__s   zInventoryManager.__init__cCs |jdS)N localhostrAget_hostrJrrrrNszInventoryManager.localhostcCs|jjSr')rAgroupsrQrrrrRszInventoryManager.groupscCs|jjSr')rAhostsrQrrrrSszInventoryManager.hostscCs|j|||Sr')rAadd_host)rJhostgroupr<rrrrTszInventoryManager.add_hostcCs |j|Sr')rA add_group)rJrVrrrrWszInventoryManager.add_groupcCs |jSr')rAget_groups_dictrQrrrrXsz InventoryManager.get_groups_dictcCs||jSr') clear_cachesrAreconcile_inventoryrQrrrrZsz$InventoryManager.reconcile_inventorycCs |j|Sr'rO)rJhostnamerrrrPszInventoryManager.get_hostcCsRtdg}tjD],}t|}|r2||qtd|q|sNtd|S)z, sets up loaded inventory plugins for usage zsetting up inventory pluginsz,Failed to load inventory plugin, skipping %sz^No inventory plugins available to generate inventory, make sure you have at least one enabled.) displayZvvvvCZINVENTORY_ENABLEDrgetr#warningr)rJZpluginsnamepluginrrr_fetch_inventory_pluginss    z)InventoryManager._fetch_inventory_pluginsFcCsd}|jD]6}|r d|vr&t|dd}|j||d}|r |s d}q |rR|jn tjrbtdntjrrt d|j D]"}t |jt|j|j|gd|_q||j D]"}t |jt|j|j|gd|_qd S) zA iterate over inventory sources and parse each one to populate itFr.)followr>TzENo inventory was parsed, please check your configuration and options.z=No inventory was parsed, only implicit localhost is available inventoryN)rFr parse_sourcerArZr]ZINVENTORY_UNPARSED_IS_FAILEDrZINVENTORY_UNPARSED_WARNINGr\r_rRvaluesrvarsrr@rS)rJr?parsedsourcerLrVrUrrrrGs$      zInventoryManager.parse_sourcesc Csd}g}td|t|}tj|rtd|tt|D]\}td|t |rdqFt tj ||dd}|j ||d}td||f|sF|}qFn||j _|D]} t t| d t| d d } td | | jfzt| |} Wntyd} Yn0| rDzZ| j|j |j||dz | WntyTYn0d }td|| fWqXWnty} zJtd|| fd ttd} ||| | | dWYd} ~ npd} ~ 0ty@} zNtd| |fd ttd} ||| t | | dWYd} ~ n d} ~ 00qtd| |fq|rr|j j!|j jn|dkstj"|r|r|D]J}t#dt |d|dt |dfd|vrtt |dqt$j%rt d|nt#d|d|j _|S)z6 Generate or update inventory for the source provided Fz'Examining possible inventory source: %sz.Searching for inventory files in directory: %szConsidering %sr+r,r>zparsed %s as %sZ _load_name_original_pathz Attempting to use plugin %s (%s)Tz)Parsed %s inventory source with %s pluginz%s was not parsable by %s)srcraexctbNz&%s failed while attempting to parse %szB%s declined parsing %s as it did not pass its verify_file() methodz/etc/ansible/hostsz( * Failed to parse %s with %s plugin: %srmrarnroz.Completely failed to parse inventory source %sz)Unable to parse %s as an inventory source)&r\debugr ospathisdirsortedlistdirIGNOREDsearchrjoinrerAZcurrent_sourcerbgetattrrjboolZ verify_filer6rLr@Zupdate_cache_if_changedAttributeErrorZvvvr traceback format_tbsysexc_infor#rZprocessed_sourcesexistsr_r]Z INVENTORY_ANY_UNPARSED_IS_FAILED)rJrir?rhZfailuresZb_sourceifullpathZparsed_this_oneraZ plugin_nameZ plugin_wantseroZfailrrrresn      (0( zInventoryManager.parse_sourcecCsi|_i|_dS)z clear all caches N)rDrErQrrrrYRszInventoryManager.clear_cachescCs`|t|_|jdd|jD]}||ddiq"|jD]\}}d|d<|||q>dS)z recalculate inventory Fr>refreshTN)rYr rArGrHadd_dynamic_hostrIadd_dynamic_group)rJrUresultrrrrefresh_inventoryWs  z"InventoryManager.refresh_inventorycCszz4|ddks tt|}nt|dd}WntyRtd|Yn0g}|D]}||r\||q\|S)Nr~zInvalid host list pattern: %s)rcompilefnmatch translater6rmatchr#)rJitemsZ pattern_strr9r:itemrrr _match_listcs    zInventoryManager._match_listr"c shg}t|tr|dd}n|g}|rd|s>jr>|j|sTjrT|jt|}|jvrt|}|}|sjrt ddjDfdd|D}|sʈjrʇfdd|D}t |j|<|dvrt j|ddt d|d kd }n\|d kr(j|ddd }n<j|dd}|d krNt |n|dvrdtd||S)z Takes a pattern or list of patterns and returns a list of matching inventory host names, taking into account any active restrictions or applied subsets Ncss|] }|jVqdSr'Z_uuid)rsrrrr*rz-InventoryManager.get_hosts..csg|]}|jvr|qSrrrh) subset_uuidsrrrrz.InventoryManager.get_hosts..csg|]}|jjvr|qSr)r`rBrrQrrrr)rtreverse_sortedr`r)keyreverseZreverse_inventoryr)Nrdz1Invalid 'order' specified for inventory hosts: %s)r0r1rCextendrBtuplerDr(_evaluate_patternssetrrtrrr ) rJr9Z ignore_limitsZignore_restrictionsorderrSZ pattern_listZ pattern_hashr$r)rJrr get_hoststs:          &     zInventoryManager.get_hostscst|}g}|D]}||jjvr4||j|q|||ddkrftfdd|D}q|ddkrtfdd|D}qtdd|D|fd dDq|S) z Takes a list of patterns and returns a list of matching host names, taking into account any negative and intersection patterns. rr csg|]}|vr|qSrrrthatrrrrz7InventoryManager._evaluate_patterns..r!csg|]}|vr|qSrrrrrrrrcss|] }|jVqdSr'r`)ryrrrr*rz6InventoryManager._evaluate_patterns..csg|]}|jvr|qSrrr)existing_hostsrrrr)r&rArSr#rP_match_one_patternrr)rJr$rSr%r)rrrrs    z#InventoryManager._evaluate_patternscCs~|ddvr|dd}||jvrt||\}}||}z|||}Wntyhtd|Yn0||j|<|j|S)a Takes a single pattern and returns a list of matching host names. Ignores intersection (&) and exclusion (!) specifiers. The pattern may be: 1. A regex starting with ~, e.g. '~[abc]*' 2. A shell glob pattern with ?/*/[chars]/[!chars], e.g. 'foo*' 3. An ordinary word that matches itself only, e.g. 'foo' The pattern is matched using the following rules: 1. If it's 'all', it matches all hosts in all groups. 2. Otherwise, for each known group name: (a) if it matches the group name, the results include all hosts in the group or any of its children. (b) otherwise, if it matches any hosts in the group, the results include the matching hosts. This means that 'foo*' may match one or more groups (thus including all hosts therein) but also hosts in other groups. The built-in groups 'all' and 'ungrouped' are special. No pattern can match these group names (though 'all' behaves as though it matches, as described above). The word 'ungrouped' can match a host of that name, and patterns like 'ungr*' and 'al*' can match either hosts or groups other than all and ungrouped. If the pattern matches one or more group names according to these rules, it may have an optional range suffix to select a subset of the results. This is allowed only if the pattern is not a regex, i.e. '~foo[1]' does not work (the [1] is interpreted as part of the regex), but 'foo*[1]' would work if 'foo*' matched the name of one or more groups. Duplicate matches are always eliminated from the results. r)r!r rNz-No hosts matched the subscripted pattern '%s')rE_split_subscript_enumerate_matches_apply_subscript IndexErrorr)rJr9exprslicerSrrrrs&      z#InventoryManager._match_one_patterncCs||ddkr|dfSd}t|}|rt|\}}}}}|rJt|df}n*|sRd}t|t|f}|dkrttd||fS)aa Takes a pattern, checks if it has a subscript, and returns the pattern without the subscript and a (start,end) tuple representing the given subscript (or None if there is no subscript). Validates that the subscript is in the right syntax, but doesn't make sure the actual indices make sense in context. rrNr-zFUse [x:y] inclusive subscripts instead of [x-y] which has been removed)PATTERN_WITH_SUBSCRIPTrrRintr\r_)rJr9 subscriptmidxstartsependrrrrs   z!InventoryManager._split_subscriptcCsJ|r|s |S|\}}|r<|dkr,t|d}|||dS||gSdS)z Takes a list of hosts and a (start,end) tuple and returns the subset of hosts based on the subscript (which may be None to return all hosts). rrN)len)rJrSrrrrrrrs z!InventoryManager._apply_subscriptc s g}||jj}|r8|D]}||jj|q|r^ddks^tfdddDr||jj}|r|D]}||jj|qv|stj vr|j }|r|||s|sdkrd}t |tj dkrt |ntj d krt||S) z Returns a list of host names matching the given pattern according to the rules explained above in _match_one_pattern. rrc3s|]}|vVqdSr'r)rZspecialr9rrr*<rz6InventoryManager._enumerate_matches..).?*[r"z3Could not match supplied host pattern, ignoring: %sr_error)rrArRrranyrSr#r] LOCALHOSTrPr\rpZHOST_PATTERN_MISMATCHr_r) rJr9r:Zmatching_groupsZ groupnameZmatching_hostsr[Zimplicitmsgrrrr.s,&      z#InventoryManager._enumerate_matchescCs*||}t|dkr&|tjvr&|g}|S)z* return a list of hostnames for a pattern r)rrr]r)rJr9rrrr list_hostsUs zInventoryManager.list_hostscCst|jjSr')rtrArRkeysrQrrr list_groups`szInventoryManager.list_groupscCs4|dur dSt|ts|g}tdd|D|_dS)z Restrict list operations to the hosts given in restriction. This is used to batch serial operations in main playbook code, don't use this for other reasons. Ncss|]}t|jVqdSr')rr`rrrrr*nrz5InventoryManager.restrict_to_hosts..)r0r1rrB)rJZ restrictionrrrrestrict_to_hostsds  z"InventoryManager.restrict_to_hostsc Cs|durd|_nt|}g}|D]}|s*q |ddkrt|dd}tj|s^td|tj|svtd|t|.}| dd| d DWdq1s0Yq | t |q ||_dS) a0 Limits inventory results to a subset of inventory that matches a given pattern, such as to select a given geographic of numeric slice amongst a previous 'hosts' selection that only select roles, or vice versa. Corresponds to --limit parameter to ansible-playbook Nr@rzUnable to find limit file %sz;Limit starting with "@" must be a file, not a directory: %scSsg|]}t|qSr)rr/)rlrrrrrz+InventoryManager.subset.. )rCr(r rqrrrrisfileopenrreadr5r#r)rJZsubset_patternZsubset_patternsr:rZ b_limit_filefdrrrsubsetps"      >zInventoryManager.subsetcCs d|_dS)z! Do not restrict list operations N)rBrQrrrremove_restrictionsz#InventoryManager.remove_restrictioncCs i|_dSr')rErQrrrclear_pattern_cachesz$InventoryManager.clear_pattern_cachec Csd}|ds|j||r|d}||jvrB||dd}|j|}|}t||dt}||kr|||_d}|dg}|D]<} | |j vr|j | } d}|j | } | |j|rd}q|r| ||d<d S) zX Helper function to add a new host to inventory based on a task result. Fr host_namer"TZ host_varsrRchangedN) r^rHr#rSrTZget_varsrdictrgrRrArWrZ) rJZ host_info result_itemrrZnew_hostZ new_host_varsZnew_host_combined_varsZ new_groups group_nameZ new_grouprrrrs2          z!InventoryManager.add_dynamic_hostc Cs4d}|ds|j||f|j|j}|durh|j|jjkrJ|j}n|dsdtd|jndS|d}|dg}||jvr||}|D]}||jvr||d}q|j j|}|D]$} |j| } | |} | r|sd}q|| vr| |}|| vr||}|r(|||d<dS) z Helper function to add a group (if it does not exist), and to assign the specified host to that group. FrNz!%s cannot be matched in inventoryrWZ parent_groupsTr)r^rIr#rSr`rNrrRrWrAZadd_child_grouprrTZ get_groupsrZ) rJrUrrZ real_hostrZparent_group_namesr`rVZparent_group_nameZ parent_groupnewrrrrs>             z"InventoryManager.add_dynamic_group)NTT)NN)F)F)r"FFN)r")"__name__ __module__ __qualname____doc__rMpropertyrNrRrSrTrWrXrZrPrbrGrerYrrrrrrrrrrrrrrrrrrrrr=sB       \  94!'  (r=);Z __future__rrrtypeZ __metaclass__rrqr~rr2r|operatorrZrandomrZansiblerr]Zansible.errorsrr r Zansible.inventory.datar Zansible.module_utils.sixr Zansible.module_utils._textr rZansible.parsing.utils.addressesrZansible.plugins.loaderrZansible.utils.helpersrZansible.utils.pathrZansible.utils.displayrZansible.utils.varsrZansible.vars.pluginsrr\ZIGNORED_ALWAYSZINVENTORY_IGNORE_PATTERNSZIGNORED_PATTERNSZINVENTORY_IGNORE_EXTSZ IGNORED_EXTSrrxrvr8rr&r(objectr=rrrrsB             .