o nnht@s<ddlmZddlZddlmZmZmZmZddlm Z ddl m Z ddl mZmZmZddlmZddlmZmZdd lmZdd lmZdd lmZdd lmZdd lmZddl m!Z!ddl"m#Z#ddl$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+ddl,m-Z-ddl.m/Z/ddgZ0ddZ1Gdddeee%eeZ2dS)) annotationsN) ContainerMappingSetSequence)MappingProxyType) constants) AnsibleErrorAnsibleParserErrorAnsibleAssertionError)to_text) binary_type text_type)FieldAttribute)Base)CollectionSearch) Conditional) Delegatable)load_list_of_blocks) RoleMetadata)Taggable)add_all_plugin_dirs)AnsibleCollectionConfig) is_subpath)Sentinel) combine_varsRole hash_paramsc Cst|trpt|ttfspt|tr>z t|}W|Sty=t}|D] \}}| |t |fq(t|}Y|Swt|t t frjzt|}W|Styit}|D] }| t |qXt|}Y|Swt|}|St|fS)a Construct a data structure of parameters that is hashable. This requires changing any mutable data structures into immutable ones. We chose a frozenset because role parameters have to be unique. .. warning:: this does not handle unhashable scalars. Two things mitigate that limitation: 1) There shouldn't be any unhashable scalars specified in the yaml 2) Our only choice would be to return an error anyway. ) isinstancerrr r frozensetitems TypeErrorsetaddrrr)params new_paramskvr(I/usr/local/lib/python3.10/dist-packages/ansible/playbook/role/__init__.pyr3s4       cs"eZdZd>fdd ZddZd?dd Zd d Zd d ZddZe d>ddZ d@ddZ ddZ ddZ ddZdAddZddZddZd d!Zd"d#Zd@d$d%ZdAd&d'Zd@d(d)ZdBd*d+Zd,d-Zd.d/Zd0d1Zd@d2d3Zd4d5Zd@d6d7Zd?fd8d9 Zd?fd:d; Zd z Role.__init__cCs|SN)get_namerIr(r(r)__repr__sz Role.__repr__cCs&|rddd|j|jfDS|jS)N.css|]}|r|VqdSrQr().0xr(r(r) sz Role.get_name..)joinr.r,)rIinclude_role_fqcnr(r(r)rRsz Role.get_namecCstj|jSrQ)ospathrealpathr-rSr(r(r) get_role_pathszRole.get_role_pathc CsP|jr|jSt||t||j|jt|jt|j|j d|_|jS)N)namer\r$whentagsrKvarsrE) rFrrRr^get_role_paramsr`rarDrbrErSr(r(r)_get_hash_dicts  zRole._get_hash_dictcCst|tsdS||kSNF)rrrd)rIotherr(r(r)__eq__s z Role.__eq__c Cs|duri}z1t||||||d}|j||d|} | |jvr&g|j| <||j| vr5|j| ||WStyEtd|jdw)N)rJrKrErLr6r2) parent_rolezvA recursion loop was detected with the roles specified. Make sure child roles do not have dependencies on parent roles)obj)r_load_role_datar^ role_cacheappend RuntimeErrorr _ds) role_includerJrhrKrErLr6r2r role_pathr(r(r)loads    z Role.loadc s|j_|_|j_|_|_| _ |r# |j D]}t d|t|d|tq&jdjddd_jdurOi_n tjts\tdjjdjddd_jdurri_n tjtstdjd}|rtj|jj d __g_jrjd jntj }|rjd |t!jjjrʈj"fd d jjDjrjrd nd}d jvrdjvrj#|jdjdd}j$r%}&||}|r&zt'|j(j jd_)Wnt*y%} z tdj|| dd} ~ wwjdjdd} | r]zt'| j(dj jd_+WdSt*y\} z tdj| | dd} ~ wwdS)N_rbT)main allow_dirzKThe vars/main.yml file for role '%s' must contain a dictionary of variablesdefaultszOThe defaults/main.yml file for role '%s' must contain a dictionary of variablesmeta)ownervariable_managerloaderrc3s|] }|jvr|VqdSrQ) collections)rVcrSr(r)rXsz'Role._load_role_data..zansible.builtinzansible.legacytasksrt)rJrolerzryzBThe tasks/main.yml file for role '%s' must contain a list of tasks)riorig_exchandlers)rJr use_handlersrzryzEThe handlers/main.yml file for role '%s' must contain a list of tasks),rr,r^r-r.rcr0get_variable_manager_variable_manager get_loaderr1 add_parent fattributessetattrgetattrr_load_role_yamlrDgetr@rrr r?rrrr7_load_dependenciesr:r{insertrdefault_collectionrextendrlrC_get_role_argspecs_prepend_validation_taskrr8r<AssertionErrorr=) rIrorh attr_namemetadatardefault_append_collection task_data role_argspecse handler_datar(rSr)rjs~      "           zRole._load_role_datac Cs~tj|jdd}tjD]+}||}|j|r7|jddd}z | dp&iWSt y6iYSwq t |j diS)aGet the role argument spec data. Role arg specs can be in one of two files in the role meta subdir: argument_specs.yml or main.yml. The former has precedence over the latter. Data is not combined between the files. :returns: A dict of all data under the top-level ``argument_specs`` YAML key in the argument spec file. An empty dict is returned if there is no argspec data. rwargument_specsr~) r[r\rYr-r3YAML_FILENAME_EXTENSIONSr1 path_existsrrAttributeErrorrr7)rIbase_argspec_pathext full_pathrr(r(r)r"s     zRole._get_role_argspecscCsD|r |jdd}||}|r |||}|sg}|d||S)aInsert a role validation task if we have a role argument spec. This method will prepend a validation task to the front of the role task list to perform argument spec validation before any other tasks, if an arg spec exists for the entry point. Entry point defaults to `main`. :param task_data: List of tasks loaded from the role. :param argspecs: The role argument spec data dict. :returns: The (possibly modified) task list. r}rtr)rDr_create_validation_taskr)rIrargspecs entrypointentrypoint_arg_specvalidation_taskr(r(r)r>s    zRole._prepend_validation_taskcCsPd|}d|vr|d|d}d|di|jd|j||jdd|d gd S) aCreate a new task data structure that uses the validate_argument_spec action plugin. :param argument_spec: The arg spec definition for a particular role entry point. This will be the entire arg spec for the entry point as read from the input file. :param entrypoint_name: The name of the role entry point associated with the supplied `argument_spec`. z*Validating arguments against arg spec '%s'short_descriptionz - z&ansible.builtin.validate_argument_specoptionsr)typer_argument_spec_namer\)module argument_specprovided_argumentsvalidate_args_contextalways)actionr_ra)rr0r,r-)rIrentrypoint_name task_namer(r(r)r[s   zRole._create_validation_taskc Csd}tj|j|}|j|r}|j|r}gd}|dur&d}|dn|}|dd|j ||||}|rq|D]3} t | |sPt dt | |j t |f|j| } | rn|durgt| trgt|| }n| }|sn|Sq;|S|dur}t d||f|S)aj Find and load role YAML files and return data found. :param subdir: subdir of role to search (vars, files, tasks, handlers, defaults) :type subdir: string :param main: filename to match, will default to 'main.' if not provided. :type main: string :param allow_dir: If true we combine results of multiple matching files found. If false, highlander rules. Only for vars(dicts) and not tasks(lists). :type allow_dir: bool :returns: data from the matched file(s), type can be dict or list depending on vars or tasks. N)z.ymlz.yamlz.jsonrtrzRFailed loading '%s' for role (%s) as it is not inside the expected role path: '%s'z,Could not find specified file in role: %s/%s)r[r\rYr-r1r is_directoryrlrfind_vars_filesrr r r,load_from_filerrr) rIsubdirrtrudata file_path extensions_main found_filesfoundnew_datar(r(r)rzs:      zRole._load_role_yamlcCs6g}|jjD]}tj||j||jd}||q|S)zr Recursively loads role dependencies from the metadata list of dependencies, if it exists )rJrhr2)r7 dependenciesrrrr8r2rl)rIdepsrorpr(r(r)rs   zRole._load_dependenciescCs.t|tst||jvr|j|dSdS)z/ adds a role to the list of this roles parents N)rrr r9rl)rIrhr(r(r)rs  zRole.add_parentcCs|jSrQ)r9rSr(r(r) get_parentsszRole.get_parentscCs,g}|jD]}||||q|SrQ)r9r get_dep_chainrl)rI dep_chainparentr(r(r)rs   zRole.get_dep_chaincCs\|durgn|}t}|D] }t||}q|r&|D]}t||j}qt||j}|SrQ)r/get_all_dependenciesrget_default_varsr?)rIr default_varsdeprr(r(r)rs  zRole.get_default_varscCsD|durgn|}t}|r |D]}|st||j}t||j}q|SrQ)r/rrbr@)rIr only_exportsinherited_varsrr(r(r)get_inherited_varss zRole.get_inherited_varscCs>|durgn|}i}|r|D]}t||j}qt||j}|SrQ)rr0)rIrr$rr(r(r)rcs zRole.get_role_paramscCs|durgn|}i}|j||d}g}|D]}||vr,t||jddd}||qt||j}|sF|r@t||j|d}t||j}|S)N)rFT)include_paramsr)r)rrrget_varsrlr@rcrb)rIrrrall_varsseenrr(r(r)rs    z Role.get_varscC|jddSrQ)r:rSr(r(r)get_direct_dependencieszRole.get_direct_dependenciescCsJ|jdur"g|_|D]}|D]}|j|q|j|q |jS)z Returns a list of all deps, built recursively from all child dependencies, in the proper order in which they should be executed or evaluated. N)r;rrrl)rIr child_depr(r(r)rs   zRole.get_all_dependenciescCrrQ)r<rSr(r(r)get_task_blocks&rzRole.get_task_blocksc Cs|jr|jSg|_}|durg}||g}|D]}|j||d}||q|jD]}|}||_||_||q,|S)NrJr) r>rget_handler_blocksrr=copy _dep_chainr8rl) rIrJr block_list new_dep_chainr dep_blocks task_blocknew_task_blockr(r(r)r)s      zRole.get_handler_blockscCs |j|jvS)zs Returns true if this role has been iterated over completely and at least one task was run )r_rB)rIhostr(r(r)has_runEs z Role.has_runcCsddlm}ddlm}g}|durg}||g}|}|D]}|j||d} || q|jD]} | } || _ || _ | | q1||d} |j | _ || _ |j| _d| _|| d} || _ d | _d d i| _d | _d g| _d | _| g| _| | |S)a Returns the task list for this role, which is created by first recursively compiling the tasks for all direct dependencies, and then adding on the tasks for this role. The role compile() also remembers and saves the dependency chain with each task, so tasks know by which route they were found, and can correctly take their parent's tags/conditionals into account. r)Block)TaskNr)rJF)blockrw _raw_params role_completeTr)ansible.playbook.blockransible.playbook.taskrrcompilerr<rrr8rlr1_rolerrun_oncerargsimplicitrar`r)rIrJrrrrrrrrrr eor_blockeor_taskr(r(r)rMs<         z Role.compilecstt|}|j|d<|j|d<|j|d<|j|d<|j|d<|j |d<|j |d<|j |d<|rKg}| D] }| |q=||d <g}|jD] }| |jd d qP||d <|S) Nr,r-r@r0r?rArBr7r:F include_depsr9)rGr serializer,r-r@r0r?rArrBr7rrlr9)rIrresrrparentsrrOr(r)rs&       zRole.serializec s(|dd|_|dd|_|dt|_|dt|_|dt|_|dt|_|dt|_|rVg}|d gD]}t }| || |q@t |d ||d g}g}|D]}t }|j |d d | |q`t |d ||d } | rt } | | | |_tt | |dS)Nr,rr-r@r0r?rArBr:r9Frr7)rr,r-r/r@r0r?rArBr deserializerlrrr7rG) rIrrrrrp parent_datarr metadata_datamrOr(r)rs6        zRole.deserializecCs8||_|jD]}||q|D]}||qdSrQ)r1r9 set_loaderr)rIrzrrr(r(r)rs     zRole.set_loader)NNFTNT)TrQre)NTF)"__name__ __module__ __qualname__rHrTrRr^rdrg staticmethodrrrjrrrrrrrrrrrcrrrrrrrrrr __classcell__r(r(rOr)rcs>,   S 6  !  2!)3 __future__rr[collections.abcrrrrtypesransiblerr3ansible.errorsr r r +ansible.module_utils.common.text.convertersr ansible.module_utils.sixr ransible.playbook.attributeransible.playbook.baser!ansible.playbook.collectionsearchransible.playbook.conditionalransible.playbook.delegatableransible.playbook.helpersransible.playbook.role.metadataransible.playbook.taggableransible.plugins.loaderransible.utils.collection_loaderransible.utils.pathransible.utils.sentinelransible.utils.varsr__all__rrr(r(r(r)s0                 0