a )gk@sddlmZmZmZeZddlmZddlZddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlmZddlmZddlmZddlmZddlmZddlm Z m!Z!dd l"m#Z#m$Z$dd l%m&Z&m'Z'dd l(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1dd l2m3Z3dd l4m5Z5ddl6m7Z7ddl8m9Z9ddl:m;Z;mZ>ddl?m@ZAddlBmCZCddlDmEZEmFZFddlGmHZHmIZImJZJddlKmLZLddlMmNZNddlOmPZPddlQmRZRddlSmTZTddlUmVZVddlWmXZXddlYmZZZeXZ[eLj\j]j^j_Z_gdZ`ddid d!d"igid#d!d$igd%ddid&Zad'd(Zbdd9d:Zjekd;krejdS)?)absolute_importdivisionprint_function)CLIN) dataclass) YAMLError)context)option_helpers) AnsibleErrorAnsibleOptionsError)Galaxy get_collections_galaxy_meta_info) GalaxyAPI GalaxyError) build_collectiondownload_collectionsfind_existing_collectionsinstall_collectionspublish_collectionvalidate_collection_namevalidate_collection_pathverify_collectionsSIGNATURE_COUNT_RE)ConcreteArtifactsManager) GPG_ERROR_MAP) Requirement) GalaxyRole)BasicAuthToken GalaxyToken KeycloakTokenNoTokenSentinel) __version__) is_iterable) yaml_dump yaml_load)to_bytes to_nativeto_text)six) DataLoader) AnsibleLoader)RoleRequirement)Templar)AnsibleCollectionConfig)Display)get_versioned_doclink) )urlTstr)usernameFr1)passwordFr1)tokenFr1)auth_urlFr1)v3Fbool)validate_certsFr7) client_idFr1)timeoutFintdefaultFalseclinamer8Z60r:)r<r>)r6r8r:r4cstfdd}|S)zInject an artifacts manager if not passed explicitly. This decorator constructs a ConcreteArtifactsManager and maintains the related temporary directory auto-cleanup around the target method invocation. csd|vr|i|Sdtjdi}tjdd}|durf|t|tjddtjdddtjtj fi|&}||d<|i|WdS1s0YdS)Nartifacts_managerr8resolved_validate_certskeyringrequired_valid_signature_countignore_gpg_errors)rBZrequired_signature_countZignore_signature_errors) rCLIARGSgetupdate GalaxyCLI _resolve_pathrZ under_tmpdirCZDEFAULT_LOCAL_TMP)argskwargsZartifacts_manager_kwargsrBZconcrete_artifact_cmwrapped_method6/usr/lib/python3.9/site-packages/ansible/cli/galaxy.pymethod_wrapper`s$  z9with_collection_artifacts_manager..method_wrapper) functoolswraps)rNrQrOrMrP!with_collection_artifacts_managerYsrT c CsBtdj|||dtt||gdtt||g||ddS)Nz) # {0} {1:{cwidth}} {2:{vwidth}} {3} {4} -)cwidthvwidth)displayformatmaxlen)pathZh1Zh2Zw1Zw2rOrOrP_display_headerysr_cCs:|j}d}|r|dd}|s"d}td|j|fdS)Nversionz(unknown version)z- %s, %s) install_inforFrZr?)grrar`rOrOrP _display_roles rcc Cs0tdjt|j|jt||t||ddS)Nz"{fqcn:{cwidth}} {version:{vwidth}})fqcnr`rXrY)rZr[r'rdverr\) collectionrXrYZ min_cwidthZ min_vwidthrOrOrP_display_collections rgcCsRt|s|f}dd|D}dd|D}tt|td}tt|td}||fS)NcSsh|]}t|jqSrO)r'rd.0crOrOrP z)_get_collection_widths..cSsh|]}t|jqSrO)r'rerhrOrOrPrkrlkey)r"r]r\) collectionsZfqcn_setZ version_setZ fqcn_lengthZversion_lengthrOrOrP_get_collection_widthssrpcCs&tt|}|dur"t|d|S)Nz% is not a valid signature count value)rematchr ValueError)valuerrrOrOrPvalidate_signature_counts ruc@s8eZdZUejedfed<eeed<eddZ dS)RoleDistributionServerN_api api_serversc Csb|jr |jS|jD]6}zd|jvr.||_WqJWqtyFYqYq0q|js\|jd|_|jS)NZv1r)rwrxavailable_api_versions Exception)selfZserverrOrOrPapis      zRoleDistributionServer.api) __name__ __module__ __qualname__tUnionr__annotations__listpropertyr|rOrOrOrPrvs  rvcseZdZdZdZdZfddZfddZdad d Zdbd d Z dcd dZ ddddZ deddZ dfddZ dgddZdhddZdiddZdjddZdkddZdldd Zdmd!d"Zfd#d$Zfd%d&Zed'd(Zd)d*Zdnd,d-Zd.d/Zedod1d2Zed3d4Zed5d6Zed7d8Z dpd9d:Z!d;d<Z"d=d>Z#d?d@Z$e%dqdAdBZ&dCdDZ'dEdFZ(e%drdGdHZ)e%dsdIdJZ*dKdLZ+dMdNZ,dOdPZ-dQdRZ.dSdTZ/e%dtdUdVZ0dWdXZ1dYdZZ2d[d\Z3d]d^Z4d_d`Z5Z6S)urHzCommand to manage Ansible roles and collections. None of the CLI tools are designed to run concurrently with themselves. Use an external scheduler and/or locking to ensure there are no clashing operations. zansible-galaxy)r? descriptionZ readme_htmlZrelatedsummary_fieldsZaverage_aw_compositeZaverage_aw_scorer0cs||_d|_t|dkrz|ddvrFd|vrFd|vrF|ddd|_|ddddgkrztd ttj t dg|_ d|_ d|_tt||dS) NF)z-hz--helpz --versionrolerfTZlogina$The login command was removed in late 2020. An API key is now required to publish roles or collections to Galaxy. The key can be found at https://galaxy.ansible.com/me/preferences, and passed to the ansible-galaxy CLI via a file at {0} or (insecurely) via the `--token` command-line argument.) _raw_args_implicit_roler]insertrZerrorr[r'rJZGALAXY_TOKEN_PATHsysexitrxgalaxy lazy_role_apisuperrH__init__)r{rK __class__rOrPrs"   zGalaxyCLI.__init__c sBtt|jddtjjdd}|jddddd |jd d d d d |jddddddd|jddtdddt|tjjdd}|jdddddddtjjdd}|jdd d!|jd"d#d!tjjdd}|jd$d%ddd&d't j d( d)d*}tjjdd}|jd+d,d-tj d.d/t jtjd0|d1tjjdd}|jd+d2d3tj d.d/tjtjd4tjjd1tjjdd}|jd5d6ddd7d|jd8d9ddd:d|jjd;dd?d!} | j|jd@| jdAdBd=} d.| _|j| ||gdC|j| ||gdC|j| ||gdC|j| |gdC|j | |||gdC|j!| ||gdC|j"| ||gdC| jdDdEd!} | j|j#d@| jdFdBd=} d.| _|j| |||gdC|j$| ||gdC|j%| ||gdC|j!| ||gdC|j&| |gdC|j'| ||gdC|j(| ||gdC|j)| |||gdC|j | |||gdCdS)Gz* create an options parser for bin/ansible z7Perform various Role and Collection related operations.)ZdescF)add_helpz-sz--server api_serverzThe Galaxy API server URLdesthelpz--tokenz --api-keyapi_keyz[The Ansible Galaxy API key which can be found at https://galaxy.ansible.com/me/preferences.z-cz--ignore-certs store_true ignore_certsz)Ignore SSL certificate validation errors.N)actionrrr<z --timeoutr:<zKThe time to wait for operations against the galaxy server, defaults to 60s.rtyper<rz-fz--forceforcez0Force overwriting an existing role or collectionrrr<r github_userGitHub usernamer github_repoGitHub repository --offlineofflinez.Don't query the galaxy API when creating roles)rr<rrDEFAULT_ROLES_PATHr<-p --roles-path roles_pathT)pathsepz}The path to the directory containing your roles. The default is the first writable one configured via DEFAULT_ROLES_PATH: %s )rrr<rr--collections-pathcollections_pathzOne or more directories to search for collections in addition to the default COLLECTIONS_PATHS. Separate multiple paths with '{0}'.z--clear-response-cacheclear_response_cachez)Clear the existing server response cache.z --no-cacheno_cachez%Do not use the server response cache.ZTYPEr)metavarrrfz$Manage an Ansible Galaxy collection.funcCOLLECTION_ACTIONr)parentsrzManage an Ansible Galaxy role.Z ROLE_ACTION)*rrH init_parseropt_helpargparseArgumentParser add_argumentr;Zadd_verbosity_optionsrJconfigZget_configuration_definitionrFZ unfrack_pathrZPrependListActionr-collection_pathsr[osr^rparseradd_subparsersrequired add_parser set_defaultsexecute_collectionadd_download_optionsadd_init_optionsadd_build_optionsadd_publish_optionsadd_install_optionsadd_list_optionsadd_verify_options execute_roleadd_remove_optionsadd_delete_optionsadd_search_optionsadd_import_optionsadd_setup_optionsadd_info_options)r{commonrZgithubrZdefault_roles_pathrrZ cache_optionsZ type_parserrfZcollection_parserrZ role_parserrrOrPrs       zGalaxyCLI.init_parserNcCs|jd|dd}|j|jd|jddddd |jd d d d ddd|jdddddd|jddddd|jddd dddS) NZdownloadPDownload collections and their dependencies as a tarball for an offline install.rrrrKz Collection(s)rf*rrnargs-n --no-depsno_depsrFz4Don't download collection(s) listed as dependencies.rrz--download-path download_pathz ./collectionsz-The directory to download the collections to.rr<r-r--requirements-file requirementsz9A file containing a list of collections to be downloaded.r--preallow_pre_releaseUInclude pre-release versions. Semantic versioning pre-releases are ignored by defaultrrr)rrexecute_downloadr)r{rrZdownload_parserrOrOrPr>s$   zGalaxyCLI.add_download_optionscCs|jdkrdnd}|jd|d|d}|j|jd|jdd d d |d |jd |d||dkrptjntjd|d i}|dkrt |d<|jd|fdd| i||dkr|jdddddddS)Nrrfrinitz4Initialize new {0} with the base structure of a {0}.rrz --init-path init_path./zaThe path in which the skeleton {0} will be created. The default is the current working directory.rz--{0}-skeleton {0}_skeletonzAThe path to a {0} skeleton that the new {0} should be based upon.r{0}_namerz{0} namez--type role_typestorer<z_Initialize using an alternate role type. Valid types include: 'container', 'apb' and 'network'.r) rrr[r execute_initrrJZGALAXY_COLLECTION_SKELETONZGALAXY_ROLE_SKELETONr capitalize)r{rr galaxy_typerZobj_name_kwargsrOrOrPrQs8  zGalaxyCLI.add_init_optionscCs4|jd|dd}|j|jd|jddddd dS) NremovezDelete roles from roles_path.rrrKzRole(s)r+r)rrexecute_remover)r{rrZ remove_parserrOrOrPrlszGalaxyCLI.add_remove_optionscCs"|jd|dd}|j|jddS)NdeletezWRemoves the role from Galaxy. It does not remove or alter the actual GitHub repository.rr)rrexecute_delete)r{rrZ delete_parserrOrOrPrrszGalaxyCLI.add_delete_optionscCsld}|jdkrd}|jd|d|d}|j|jd|j||d|d |dkrh|jd d d d dddS)NrrrfrzAShow the name and version of each {0} installed in the {0}s_path.rr?)rrrz--format output_format)humanyamljsonrz-Format to display the list of collections in.)rchoicesr<r)rrr[r execute_listrr)r{rrrZ list_parserrOrOrPrxs  zGalaxyCLI.add_list_optionscCsd|jd|dd}|j|jd|jdddd|jd d d d|jd d dd|jddddddS)NsearchzLSearch the Galaxy database by tags, platforms, author and multiple keywords.rrz --platforms platformsz!list of OS platforms to filter byrz --galaxy-tags galaxy_tagsz list of galaxy tags to filter byz--authorauthorrrKz Search termsZ searchtermrr)rrexecute_searchr)r{rrZ search_parserrOrOrPrszGalaxyCLI.add_search_optionscCsj|jd|dd}|j|jd|jddddd d |jd d d d|jdddd|jdddddd dS)Nimportz"Import a role into a galaxy serverrr --no-waitwait store_falseTzDon't wait for import results.rz--branch referencez\The name of a branch to import. Defaults to the repository's default branch (usually master)rz --role-name role_namez>The name the role should have, if different than the repo namez--status check_statusrFzUCheck the status of the most recent import request for given github_user/github_repo.)rrexecute_importr)r{rrZ import_parserrOrOrPrs  zGalaxyCLI.add_import_optionscCs|jd|dd}|j|jd|jddddd|jd d d d d d|jddd|jddd|jddd|jddddS)NZsetupz;Manage the integration between Galaxy and the given source.rrz--remove remove_idzSRemove the integration matching the provided ID value. Use --list to see ID values.rz--list setup_listrFzList all of your integrations.rsourceZSourcerrrrrsecretZSecret)rr execute_setupr)r{rrZ setup_parserrOrOrPrs  zGalaxyCLI.add_setup_optionscCs4|jd|dd}|j|jd|jddddd dS) Ninfoz(View more details about a specific role.rrrKrrzrole_name[,version])rrr)rr execute_infor)r{rrZ info_parserrOrOrPrszGalaxyCLI.add_info_optionsc Csd}|jd|dd}|j|jd|jdd|dd d |jd d d dddd|jdddddd|jddddd|jddtjdd|jddd d!d"d#}d$}|jd%d&t|tjd'|jd(d)t d |tj t t d*dS)+NrfZverifywCompare checksums with the collection(s) found on the server and the installed copy. This does not verify dependencies.rrrKrrzVThe installed collection(s) name. This is mutually exclusive with --requirements-file.)rrr-i--ignore-errors ignore_errorsrFzRIgnore errors during verification and continue with the next specified collection.rrrz\Validate collection integrity locally without contacting server for canonical manifest hash.rrrz7A file containing a list of collections to be verified.r --keyringrB.The keyring used during signature verificationr --signature signaturesappenda An additional signature source to verify the authenticity of the MANIFEST.json before using it to verify the rest of the contents of a collection from a Galaxy server. Use in conjunction with a positional collection name (mutually exclusive with --requirements-file).raThe number of signatures that must successfully verify the collection. This should be a positive integer or all to signify that all signatures must be used to verify the collection. Prepend the value with + to fail if no valid signatures are found for the collection (e.g. +all).A status code to ignore during signature verification (for example, NO_PUBKEY). Provide this option multiple times to ignore a list of status codes. Descriptions for the choices can be seen at L(https://github.com/gpg/gnupg/blob/master/doc/DETAILS#general-status-codes). --required-valid-signature-countrCrrrr<--ignore-signature-status-coderDrrrrr<r)rrexecute_verifyrr[rJGALAXY_GPG_KEYRINGru%GALAXY_REQUIRED_VALID_SIGNATURE_COUNTr1,GALAXY_IGNORE_INVALID_SIGNATURE_STATUS_CODESrrkeys)r{rrrZ verify_parservalid_signature_count_helpignore_gpg_status_helprOrOrPrs8       zGalaxyCLI.add_verify_optionsc s|jdkrdnd}i}|dkr,d|d<d}n d|d<d}|jd |d |d }|j|jd |jdQd|dd||jddddd|d|}|jdddddd|d|jddddd|dd}d} |dkr|jd d!d"|d#d$|jd%d&d'd(d)|jd*d+dd,d-|jd.d/d0ddd1d|jd2d3tj d4d$|jd5d6dtj d7d|jd8d9d:d;d-|jd|jd?d@t d:| tjttdA|jdBdCdddDdn|jd%dEd'dFd)tdGtfdHdI|jD} tdJtfdKdI|jD} |jr| s$| r|jd2d3tj dLd$|jd5d6dtj d7d|jd|jd?d@t d:| tjttdA|jdMdNdOdddPddS)RNrrfrzxThe collection(s) name or path/url to a tar.gz collection artifact. This is mutually exclusive with --requirements-file.rzIgnore errors during installation and continue with the next specified collection. This will not ignore dependency conflict errors.zRole name, URL or tar filez8Ignore errors and continue with the next specified role.installz5Install {0}(s) from file(s), URL(s) or Ansible GalaxyrrrKrr)rrrrrrFrrrrz+Don't download {0}s listed as dependencies.z--force-with-depsforce_with_depsz7Force overwriting an existing {0} and its dependencies.aThe number of signatures that must successfully verify the collection. This should be a positive integer or -1 to signify that all signatures must be used to verify the collection. Prepend the value with + to fail if no valid signatures are found for the collection (e.g. +all).rrrrz6The path to the directory containing your collections.rrrrz8A file containing a list of collections to be installed.rrrrrz-Uz --upgradeupgradezgUpgrade installed collection artifacts. This will also update dependencies unless --no-deps is providedrrBrz--disable-gpg-verifydisable_gpg_verifyzSDisable GPG signature verification when installing collections from a Galaxy serverrrrzAn additional signature source to verify the authenticity of the MANIFEST.json before installing the collection from a Galaxy server. Use in conjunction with a positional collection name (mutually exclusive with --requirements-file).rrCrrrDr rrzInstall collection artifacts (tarballs) without contacting any distribution servers. This does not apply to collections in remote Git repositories or URLs to remote tarballs.z --role-filez2A file containing a list of roles to be installed.z^(?rlz1GalaxyCLI.add_install_options..z--role-file($|=)csg|]}|r|qSrOr,r-) role_file_rerOrPr0rlz9The keyring used during collection signature verificationz-gz--keep-scm-metaZ keep_scm_metazBUse tar instead of the scm archive option when packaging the role.)rK)rrr[rexecute_installradd_mutually_exclusive_group_get_default_collection_pathrJr"ZGALAXY_DISABLE_GPG_VERIFYrur#r1r$rrr%rqcompiler7rr) r{rrrZ args_kwargsZignore_errors_helpZinstall_parserZinstall_exclusiver&r'Z contains_rZcontains_role_filerO)r/r1rPrs                     zGalaxyCLI.add_install_optionscCsH|jd|dd}|j|jd|jddddd d |jd d d dddS)NZbuildzMBuild an Ansible collection artifact that can be published to Ansible Galaxy.rrrKrfr.zPath to the collection(s) directory to build. This should be the directory that contains the galaxy.yml file. The default is the current working directory.)rrr<rz --output-path output_pathrz[The path in which the collection is built to. The default is the current working directory.r)rr execute_buildr)r{rrZ build_parserrOrOrPr1s  zGalaxyCLI.add_build_optionscCsZ|jd|dd}|j|jd|jdddd|jd d d d d d|jddtddddS)NZpublishz0Publish a collection artifact to Ansible Galaxy.rrrKcollection_pathz.The path to the collection tarball to publish.)rrrrrTz)Don't wait for import validation results.rz--import-timeoutimport_timeoutrz=The time to wait for the collection import process to finish.r)rrexecute_publishrr;)r{rrZpublish_parserrOrOrPr?s  zGalaxyCLI.add_publish_optionscsZtt||}t|d|jdur$dn|j t|d|jdurD|jntj |jt _|S)Nr8rA) rrHpost_process_argssetattrrr8rJZGALAXY_IGNORE_CERTS verbosityrZ)r{optionsrrOrPr=Ks  zGalaxyCLI.post_process_argscsztt|t|_ddi}dD]}|tjvr&tj|||<q&g}ddtjpVgD}t |ddD]0\}t fdd t D}t t |}tjd |tjd }|d } |d } |d pt} |d} |d} |ddurtjd|d<|d}| r ddi|d<d|d <| rBt| |d|d <n0| rr| rdt| | || d|d <nt| d|d <|||t|jfd|i|qhtjdttjdd}tjd}r"tfdd |Dd}|r|j|n.|jt|jdf|t|d|d|n||_t|jdkr`|jt|jdtjf|d|d|td|j|_tjdS) NcSsTd||fd||dgdd||fig||d}|tvrP|t||S)NzThe %s of the %s Galaxy serverzgalaxy_server.%s)sectionrnr?zANSIBLE_GALAXY_SERVER_%s_%s)rZinienvrr)upperSERVER_ADDITIONALrG)rArnrZ option_typeZ config_defrOrOrPserver_config_def\s z(GalaxyCLI.run..server_config_def)rrr:cSsg|] }|r|qSrOrOrisrOrOrPr0xrlz!GalaxyCLI.run..r)startc3s&|]\}}}||||fVqdSNrO)rikreqZ ensure_type)rE server_keyrOrP }rlz GalaxyCLI.run..Z galaxy_serverr5r9r4r2r6r8rAz/v3ryr3)Z access_tokenr5r8r9)r4priorityrrc3s|]}|jkr|VqdSrIr?rF) cmd_serverrOrPrMrlZcmd_arg)r4rNr8rr<r) rrHrunr rrrErJZGALAXY_SERVER_LIST enumeratedict SERVER_DEFr*r#Zget_single_datarZ+initialize_plugin_configuration_definitionsZget_plugin_optionspopr rrrrGrrnextrxr]Z GALAXY_SERVERrvr)r{Zgalaxy_optionsZ optional_keyZconfig_serversZ server_listZserver_priorityZ config_dictZdefsZserver_optionsr5r9Z token_valr2r6r8Z cmd_tokenZ config_serverr)rPrErLrPrQVs               z GalaxyCLI.runcCs|jjSrI)rr|r{rOrOrPr|sz GalaxyCLI.apicCs tjdS)Nr)rJCOLLECTIONS_PATHSrWrOrOrPr4sz&GalaxyCLI._get_default_collection_pathTc sggd}tdd}tj|s2tdttdt|dZ}z t |}Wn<t y} z$tdtt| fWYd} ~ n d} ~ 00Wdn1s0Y|durtd tfd d } t |t r|std |D]} |d | | 7<qnt |t d dg} | rHtdtd| |d pVgD]} |d | | 7<qXfdd|dpgD|d<|S)a Parses an Ansible requirement.yml file and returns all the roles and/or collections defined in it. There are 2 requirements file format: # v1 (roles only) - src: The source of the role, required if include is not set. Can be Galaxy role name, URL to a SCM repo or tarball. name: Downloads the role to the specified name, defaults to Galaxy name from Galaxy or name of repo if src is a URL. scm: If src is a URL, specify the SCM. Only git or hd are supported and defaults ot git. version: The version of the role to download. Can also be tag, commit, or branch name and defaults to master. include: Path to additional requirements.yml files. # v2 (roles and collections) --- roles: # Same as v1 format just under the roles key collections: - namespace.collection - name: namespace.collection version: version identifier, multiple identifiers are separated by ',' source: the URL or a predefined source name that relates to C.GALAXY_SERVER_LIST type: git|file|url|galaxy :param requirements_file: The path to the requirements file. :param allow_old_format: Will fail if a v1 requirements file is found and this is set to False. :param artifacts_manager: Artifacts manager. :return: a dict containing roles and collections to found in the requirements file. )rolesrosurrogate_or_stricterrorsz*The requirements file '%s' does not exist.z Reading requirement file at '%s'rbzIFailed to parse the requirements yml at '%s' with the following error: %sNz"No requirements found in file '%s'c s(d|vrTt|}tdt|d|vr.parse_role_req..css|]}t|VqdSrI)r+role_yaml_parse)riirOrOrPrMrlzMGalaxyCLI._parse_requirements_file..parse_role_req..z9Unable to load data from include requirements file: %s %s)r+rarZvvvr'r rrrr%rr^isfiler&openr$rz)Z requirementrZb_include_pathZ f_includee)requirements_filer{rOrPparse_role_req s(    z:GalaxyCLI._parse_requirements_file..parse_role_reqzrExpecting requirements file to be a dict with the key 'collections' that contains a list of collections to installrYroz\Expecting only 'roles' and/or 'collections' as base keys in the requirements file. Found: %sz, cs g|]}t|qSrO)rZfrom_requirement_dict_init_coll_req_dict)riZcollection_req)r@r{validate_signature_optionsrOrPr01s z6GalaxyCLI._parse_requirements_file..)r%rr^existsr r&rZrcrer$r isinstancersetr% differencejoinrF) r{rgallow_old_formatr@rjrZb_requirements_fileZreq_objZfile_requirementserrrhZrole_reqZ extra_keysrO)r@rgr{rjrP_parse_requirements_filesF    8   z"GalaxyCLI._parse_requirements_filecsttsdiSdvs4dr4dddkr8Sttfdd|jDt|jdjdddt j d d d<S) Nr?rrrc3s&|]}d|j|jhvr|VqdS)rN)r?r)riZsrvrcoll_reqrOrPrMLsz0GalaxyCLI._init_coll_req_dict..zexplicit_requirement_{name!s}rOrA)r8) rlrSrFrViterrxrrr[rrE)r{rtrOrsrPri<s.  zGalaxyCLI._init_coll_req_dictrcCstjdstddS)zn Exits with the specified return code unless the option --ignore-errors was specified rzR- you can use --ignore-errors to skip failed roles and finish processing the list.N)rrEr )rcrOrOrPexit_without_ignore\s zGalaxyCLI.exit_without_ignorecCsddt|dg}|di}|d|dd}|d|t|D]}|tjvr^qNt||tr|d|t||D]*}|tjvrq|d||||fqqN|d |||fqN|dd |S) NrzRole: %sr? galaxy_inforz description: %sz %s:z %s: %sz %s: %s ) r'rFrsortedr%rHSKIP_INFO_KEYSrlrSro) role_infotextrxrrJrnrOrOrP_display_role_infoes     zGalaxyCLI._display_role_infocCstjtjtj|SrI)rr^abspath expanduser expandvarsr^rOrOrPrIszGalaxyCLI._resolve_pathcstt|ddd }t|dd}Wdn1s80Yt}g}g}|D]r}|ddrh|n|}||dd} | s|dd} | dkrd } n| d krg} n | d kri} | |d <||qTtd tdfdd} t } t | ||dd} | | j j d<| |}|S)NrZr[r]rFrnrr1rrrSrtzL\(([^)]+),\s+([^)]+)\)z C\(([^)]+)\)csJt|trddd|D}d|}d|}tj|ddddd S) Nz. cSsg|]}|dqSr6)rstrip)rilrOrOrPr0rlzKGalaxyCLI._get_skeleton_galaxy_yml..comment_ify..z\1 <\2>z'\1'uz# F)widthinitial_indentsubsequent_indentZbreak_on_hyphens)rlrrosubtextwrapfill)vZ const_patternZ link_patternrOrP comment_ifys    z7GalaxyCLI._get_skeleton_galaxy_yml..comment_ify)required_configoptional_configZ variablesr)rer%r'readr rFrrqr5r)r,Z environmentfilterstemplate)Z template_path inject_dataZ template_objZ meta_templateZ galaxy_metarrZ meta_entryZ config_listrtZ meta_typerloadertemplar meta_valuerOrrP_get_skeleton_galaxy_ymls4.       z"GalaxyCLI._get_skeleton_galaxy_ymlcsr|r|rtdn\|s$|s$tdnJ|rTdur8tdt|}|j|dd}nfdd|Dgd}|S) NzRThe positional collection_name arg and --requirements-file are mutually exclusive.z:You must specify a collection name or a requirements file.zThe --signatures option and --requirements-file are mutually exclusive. Use the --signatures with positional collection_name args or provide a 'signatures' key for requirements in the --requirements-file.F)rpr@csg|]}t|qSrO)rZ from_string)riZ coll_inputr@rrOrPr0szFGalaxyCLI._require_one_of_collections_requirements..)rorY)r rHrIrr)r{rorgrr@rrOrrP(_require_one_of_collections_requirementss*    z2GalaxyCLI._require_one_of_collections_requirementscCsdS)z Perform the action on an Ansible Galaxy role. Must be combined with a further action like delete/install/init as listed below. NrOrWrOrOrPrszGalaxyCLI.execute_rolecCsdS)z Perform the action on an Ansible Galaxy collection. Must be combined with a further action like init/install as listed below. NrOrWrOrOrPrszGalaxyCLI.execute_collectioncCstjd}ttjd}t|dd}tj|s>t|ntj |rZt dt |tjdD]*}t|}t t |ddt |dd|qddS)a* Build an Ansible Galaxy collection artifact that can be stored in a central repository like Ansible Galaxy. By default, this command builds from the current working directory. You can optionally pass in the collection input path (where the ``galaxy.yml`` file is). rr8rZr[z9- the output collection directory %s is a file - abortingrKN)rrErHrIr%rr^rkmakedirsrdr r&rr')r{rr8 b_output_pathr:rOrOrPr9s        zGalaxyCLI.execute_buildcCstjd}tjd}tjd}tjd}|r6t|}|j|||dd}t|}t|dd}tj|svt |t |||j |tjd |dd S) rrKrrrr@rorZr[rr) rrErHrIrr%rr^rkrrrx)r{r@rorrrgrZb_download_pathrOrOrPrs,          zGalaxyCLI.execute_downloadc%stjd}tjd}tjd}tjd|}tjd|}td|tdd}|d kr|td d d |tjd ddddtddgd tj}t j ||}nV|dkr| dd\} } |t| | dddgdgddddgd tj }t j || | }t|dd} t j | rt j |r4tdt|n|sJtd t|t j| d!d"D]T\} } }| D]}t j | |}t|qf|D]}t j | |}t |qqX|durd#}nd!}|jj}d$g}t j |}d%d&|Dt j |s td't||t}t||d(}t j | s6t | t j|d!d"D]V\} } }t j | | t j}|d)}|dkr|d*vod+|v}n|d+k}fd,d&| D| dd<|D]t j \}}t fd-d.Drq|dkr|rdkrd/kr|!}|"d0|d1<t#$t j | |}tt j ||dd}t%|d2"}|&t|ddWdn1s0Yn|d3kr"|s"t j | }t j ||}t'|(|d)dd}t|)|dd} t%|d2}!|!&| Wdn1s0Yn8t j t j | |}"t*t j | t j ||"q| D]6}#tt j ||#dd}$t j |$sbt |$qbqDt++d4|,|fdS)5z Creates the skeleton framework of a role or collection that complies with the Galaxy metadata format. Requires a role or collection name. The collection name must be in the format ``.``. rrrrrzyour {0} descriptionzplugins/plugins.html)rZansible_plugin_list_dirrz your namezyour company (optional)z$license (GPL-2.0-or-later, MIT, etc)rz http://example.com/issue/trackerzhttp://example.com/repositoryzhttp://docs.example.comzhttp://example.comNr) rZcompanylicenser rZissue_tracker_urlZrepository_urlZdocumentation_urlZ homepage_urlZmin_ansible_versionZ dependenciesrfr7rz1.0.0z README.mdzyour name zGPL-2.0-or-later) namespacecollection_namer`ZreadmeZauthorsrZ repositoryZ documentationZhomepageZissuesZ build_ignorerZr[z6- the path %s already exists, but is a file - abortingz- the directory %s already exists. You can use --force to re-initialize this directory, however it will reset any main.yml files that may have been modified there already.T)topdownFz^.*/.git_keep$cSsg|]}t|qSrO)rqr5)rixrOrOrPr0mrlz*GalaxyCLI.execute_init..z9- the skeleton path '{0}' does not exist, cannot init {1}rr)Z playbooksrYZ templatescs&g|]tfddDsqS)c3s|]}|VqdSrIr,r_drOrPrMrlz4GalaxyCLI.execute_init...)any)ri)skeleton_ignore_rerrPr0rlc3s"|]}|tjVqdSrI)rrrr^ror_)frel_rootrOrPrMrlz)GalaxyCLI.execute_init..z galaxy.yml.j2rr?wbz.j2z - %s %s was created successfully)-rrEr[rSr/rGansible_versionrJZGALAXY_ROLE_SKELETON_IGNORErr^rosplitZ!GALAXY_COLLECTION_SKELETON_IGNOREr%rkrdr r&walkshutilrmtreeunlinkrZdefault_role_skeleton_pathrr)r,rrelpathsepsplitextrcopyrUrHrrewriter'Z_get_file_contentsrcopyfilerZtitle)%r{rrrZ obj_skeletonZobj_namerZskeleton_ignore_expressionsZobj_pathrrZ b_obj_pathrootdirsfilesZold_dirr^Zold_fileZ own_skeletonrrZrel_dirsZ rel_root_dirZin_templates_dirfilenameextZ template_datarZ b_dest_fileZ galaxy_objZ src_templateZ dest_fileZ b_renderedZdfZ f_rel_pathrZ b_dir_pathrO)rrrrPrs            $ 4 ,$zGalaxyCLI.execute_initc Cstjd}d}tjdD]V}d|i}t|j|j|}|j}|rdd|vrZ|d|d<|d=||tjdsd}z|j|d }Wn`t y}zH|j d krd |j vrd |}WYd}~qrt d ||fWYd}~n d}~00|r||nd |}qrn"tjdr*|j s*d |}qr|jr>||jt} | d|i} | rb|| |||7}q||dS)zx prints out detailed information about an installed role as well as info available from the galaxy API. rrrKr^r`Zinstalled_versionrNFiz Bad Request- the role %s was not foundz"Unable to find info about '%s': %sr)rrErrrrarGr|Zlookup_role_by_namerZ http_codemessager _existsmetadatar+rar~pager) r{rdatarr|rbraZ remote_datarfrKZ role_specrOrOrPrsF    &   zGalaxyCLI.execute_infoc Cstjd}tjd}tjd}tjd}tjd}tjd}|durLt|}|j||||dd }d d |D} t|| |j|||d } td d| DrdSdS)rrKrrrrrNrr@rocSsg|]}tt|qSrO)rrHrI)rir^rOrOrPr0rlz,GalaxyCLI.execute_verify..)local_verify_onlyr@css|]}|js|VqdSrI)success)riresultrOrOrPrMrlz+GalaxyCLI.execute_verify..rr)rrErrrrxr) r{r@roZ search_pathsrrrgrrZresolved_pathsresultsrOrOrPr!s2      zGalaxyCLI.execute_verifycCstjd}tjd}d}tjd}|dur4t|}|rBt|}dt|}g}g}tjddkrttjd}|j||||d } | d }| d rt | d n|s|durt d |rp| ds| dst d|j} |jod| vod| v} |j||| d} | d }| d r^|jr:d| vs:d| vr^|jrHtjntj } | | dn|}| d }n.rzThe specified collections path '%s' is not part of the configured Ansible collections paths '%s'. The installed collection will not be picked up in an Ansible run, unless within a playbook-adjacent collections directory.:rZr[r)rr@r+r)rrEKeyErrorrr rFrJrXr]rZrr'rorr%rr^rkrrrx)r{rr^r@rrrr)r+rr*rr8rrOrrPr_s@           z%GalaxyCLI._execute_install_collectionc Cstjd}tjd}tjd}tjdp*|}|D]}|rftjdrf|jtjdvrftd|jq0td|j|jdur|jd|jks|r|rtd |j|jd|jpd f|n$td |j|jd|jpd fq0n|std t |q0z | }WnRt yd}z8td |jt |f| WYd}~q0WYd}~n d}~00|s|r|jstd|jnT|j|j} | D]@} td| t} | | } t|j|jfi| } d| jvrd| jvr| jdurq| jdurF| |vr4tdt | || ntd| jn| jd| jkr|rtd| j| jd| jpzd f| || n$tdt | | j|j| jdfn"|r|| ntd| jq|s0td|j| q0dS)Nrrr)rrKzSkipping role %szProcessing role %s r`z - changing role %s from %s to %s unspecifiedzD- %s (%s) is already installed - use --force to change version to %sz$- %s is already installed, skipping.z(- %s was NOT installed successfully: %s z-Meta file %s is empty. Skipping dependencies.zInstalling dep %sr7z- adding dependency: %sz-- dependency %s already pending installation.z*- changing dependent role %s from %s to %szW- dependency %s (%s) from role %s differs from already installed version (%s), skippingz/- dependency %s is already installed, skipping.z$- %s was NOT installed successfully.r)rrEr?rZrcrar`rrr1r(r r'rwrr^Zmetadata_dependenciesrdebugr+rarrrr^Zscmr)r{rZ role_filerZ force_depsrrZ installedrfZrole_dependenciesZdepZdep_reqZdep_infoZdep_rolerOrOrPrs|       "    $      zGalaxyCLI._execute_install_rolec CstjdstdtjdD]x}t|j|j|}z*|rJtd|ntd|Wqty}z t d|t |fWYd}~qd}~00qdS)zV removes the list of roles passed as arguments from the local system. rKz/- you must specify at least one role to remove.z- successfully removed %sz - %s is not installed, skipping.zFailed to remove role %s: %sNr) rrEr rrr|rrZrzr r&)r{r rrfrOrOrPrs ,zGalaxyCLI.execute_removecCs2tjddkr|ntjddkr.|dS)z5 List installed collections or roles rrrfN)rrEexecute_list_roleexecute_list_collectionrWrOrOrPrs zGalaxyCLI.execute_listc Csd}d}g}tjd}tjd}|D]}t|}tj|rFd}n|d|q$|rt |j |j |tj ||d}tj|jrd}t dtj|jt|qD|d|q$tj|s|d |q$tj|s|d |q$t d|t|} | D]*} t |j |j | |d}|jrt|qq$|rT|rTg}|D]} t | qX|std tjd d S)zQ List all roles installed on the local system or a specific role FrrT)- the configured path {0} does not exist.rz# %srz(- the configured path %s does not exist.z<- the configured path %s, exists, but it is not a directory.V- None of the provided paths were usable. Please specify a valid path with --{0}s-pathrr)rrErHrIrr^isdirrr[rrrrorZdirnamercrklistdirrrr ) r{ path_foundZ role_foundwarningsZroles_search_pathsr r^Z role_pathrbZ path_filesZ path_filewrOrOrPrsL         zGalaxyCLI.execute_list_rolec Cs|durd|_tjd}ttjd}tjd}tj}i}g}d}d} |D]$} t| } tj | s| |vrpqJ| d | qJtj | s| d | qJd}|rt||d \} } t| } ttj | | | d d }tj |s| d |qJtj | s| d | qJd} zt||} Wn6tyh}ztt||WYd}~n d}~00|d vr| jd| jii|| <qJt| g\}}t| dd||t| ||qJt| } tj | rtd | t t!| |}ntd | qJ|std | qJ|d vr4dd|D|| <qJt|\}}t| dd||t"|t#dD]} t| ||q\qJ| r|rg}|D]}t$|q|st%d tjd|dkrtt&'|n|dkrtt(|dS)zz List all collections installed on the local system :param artifacts_manager: Artifacts manager. NFrrrfrz=- the configured path {0}, exists, but it is not a directory.Tr7rZr[z(- unable to find {0} in collection paths>rrr` CollectionZVersionzSearching {0} for collectionsz/No 'ansible_collections' directory found at {0}zNo collections found at {0}cSsi|]}|jd|jiqS)r`)rdre)rirfrOrOrP sz5GalaxyCLI.execute_list_collection..rmrrrrr))Zrequire_build_metadatarrErmr-rrHrIrr^rkrr[rrrrr%rorZfrom_dir_path_as_unknownrsr(Z raise_fromr rdrerpr_rgrZrcrrrzr'rr rdumpsr#)r{r@rZcollections_search_pathsrZdefault_collections_pathZcollections_in_pathsrrZcollection_foundr^r:rrfZb_collection_pathZval_errZ fqcn_widthZ version_widthrorrOrOrPr2s       &        z!GalaxyCLI.execute_list_collectioncCs8ttjd}tjd}tjd}t||j||dS)zs Publish a collection into Ansible Galaxy. Requires the path to the collection tarball to publish. rKrr;N)rHrIrrErr|)r{r:rr:rOrOrPr<s  zGalaxyCLI.execute_publishc Csd}d}tjdr"dtjd}|sLtjdsLtjdsLtjdsLtd|jj|tjdtjdtjd|d }|d d krtjd tjd dSdg}|d |kr| d|d |fn| d|d g}|dD]"}| t |dd|dqt |}d|}| d| |d| |d|dD],}| |d|d|df|dfq>d|}| |d S)z0 searches for roles on the Ansible Galaxy serveriNrKrrrrzYInvalid query. At least one search term, platform, galaxy tag or author must be provided.)rtagsr page_sizecountrzNo roles match your search.Zcolorrrz6Found %d roles matching your search. Showing first %s.z$Found %d roles matching your search:rr2r7r?z %%-%ds %%s)NameZ Description)z----z -----------%s.%srry) rrEror r|Z search_rolesrZrJ COLOR_ERRORrr]r\r) r{rrZresponserZmax_lenrZname_lenZ format_strrOrOrPrs: "      *  zGalaxyCLI.execute_searchc Csdtjtjtjtjd}ttjddd}ttjddd}tjdrZ|jj||d}n |jj ||tjd tjd d }t |d krt j d ||fddt j dtj d|D]4}t j d|ddd|dddftj dqt j d||ftj ddSt d|ddtjdsft d|ddddt d|dd|ddftjds~tjdrg}d}|s|jj|ddd}|dddD]<}|d|vrt j |d ||d!d| |dq|dd"d#vrd$}n td%qdS)&z+ used to import a role into Ansible Galaxy Znormal)INFOZWARNINGZERRORSUCCESSFAILEDrrZr[rr )rrrr )rr rzEWARNING: More than one Galaxy role associated with Github repo %s/%s.Zyellowrz.The following Galaxy roles are being updated: rrrrr?z[ To properly namespace this role, remove each of the above and re-import %s/%s from scratchrz(Successfully submitted import request %didrz Role name: %sz Repo: %s/%sF)Ztask_idZ task_messagesZ message_textZ message_typestate)rrTrU)rJZ COLOR_WARNrCOLOR_OKr'rrEr|Zget_import_taskZcreate_import_taskr]rZZ COLOR_CHANGEDrtimesleep) r{ZcolorsrrZtaskrZmsg_listfinishedmsgrOrOrPr sT  2 "zGalaxyCLI.execute_importcCstjdr|j}t|dkr.tddStjdtjdtjdtjd|D]0}tjd|d|d |d |d ftjdqRdStjd r|jtjd tjd tjddStjd }tjd }tjd }tjd}|j ||||}td|d |d |d fdS)zD Setup an integration from Github or Travis for Ansible Galaxy rolesr rzNo integrations found.z ID Source Reporz ---------- ---------- ----------z%-10s %-10s %s/%srrrrr zDSecret removed. Integrations using this secret will not longer work.rzAdded integration for %s %s/%s) rrEr|Z list_secretsr]rZrJrZ remove_secretZ add_secret)r{ZsecretsrrrrresprOrOrPrs2          zGalaxyCLI.execute_setupcCstjd}tjd}|j||}t|ddkrxtdtdtd|dD]}td|j|j|jfqXt|d d S) z$ Delete a role from Ansible Galaxy. rrZ deleted_rolesrzDeleted the following roles:zID User Namez!------ --------------- ----------z %-8s %-15s %sstatusr) rrEr|Z delete_roler]rZrrr?)r{rrrrrOrOrPr8s      zGalaxyCLI.execute_delete)N)N)N)N)N)N)N)N)N)N)N)N)N)TNT)r)NN)N)N)N)N)7r}r~r__doc__r?r{rrrrrrrrrrrrrrrr=rQrr|r4rrri staticmethodrwr~rIrrrrr9rTrrrr!r2rrrrrrr<rr rr __classcell__rOrOrrPrHsx  U         ! Y  z  e     / $ 6  Y+R 8 z )7!rHcCst|dSrI)rHZ cli_executor)rKrOrOrPmainKsr__main__)rUrV)rUrVrUrV)N)lZ __future__rrrrZ __metaclass__Z ansible.clirrRrZos.pathrrqrrrrtypingrZ dataclassesrZ yaml.errorrZansible.constantsZ constantsrJZansiblerZansible.cli.argumentsr rZansible.errorsr r Zansible.galaxyr r Zansible.galaxy.apirrZansible.galaxy.collectionrrrrrrrrrZ3ansible.galaxy.collection.concrete_artifact_managerrZansible.galaxy.collection.gpgrZ0ansible.galaxy.dependency_resolution.dataclassesrZansible.galaxy.rolerZansible.galaxy.tokenrrrr Z$ansible.module_utils.ansible_releaser!rZ'ansible.module_utils.common.collectionsr"Z ansible.module_utils.common.yamlr#r$Zansible.module_utils._textr%r&r'Zansible.module_utilsr(Zansible.parsing.dataloaderr)Zansible.parsing.yaml.loaderr*Z!ansible.playbook.role.requirementr+Zansible.templater,Zansible.utils.collection_loaderr-Zansible.utils.displayr.Zansible.utils.plugin_docsr/rZZmovesZurllibparseurlparserTrDrTr_rcrgrprurvrHrr}rOrOrOrPs      ,