o nnhcz@sddlmZddlmZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlmZddlmZddlmZddlmZddlmZddlmZmZdd 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-m.Z.m/Z/dd l0m1Z1dd l2m3Z3ddl4m5Z5ddl6m7Z7ddl8m9Z9m:Z:m;Z;mZ?ddl@mAZAddlBmCZCmDZDddlEmFZFmGZGmHZHddlImJZJddlKmLZLddlMmNZNddlOmPZPddlQmRZRddlSmTZTddlUmVZVddlWmXZXddlYmZZZeVZ[eJj\j]j^j_Z_gdZ`ddd gd!d"d#d$igiejad#d%igd&d'did(Zbd)d*Zcd>d-d.Zdd/d0Zed?d1d2Zfd3d4Zgd5d6ZheGd7d8d8ZiGd9d:d:eZjd@d;d<Zkeld=kr]ekdSdS)A) annotations)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)load_extra_vars) )urlTstr)usernameFr0)passwordFr0)tokenFr0)auth_urlFr0) api_versionFint)validate_certsFbool) client_idFr0)timeoutFr6)defaultchoicesclinamer7r:)r=r?r=)r5r7r:r3cstfdd}|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|Sdtjddi}tjdd}|dur5|t|tjddtjdddtjtj fi|}||d<|i|WdS1sUwYdS) Nartifacts_managerr7resolved_validate_certsTkeyringrequired_valid_signature_countignore_gpg_errors)rCrequired_signature_countignore_signature_errors) rCLIARGSgetupdate GalaxyCLI _resolve_pathr under_tmpdirCDEFAULT_LOCAL_TMP)argskwargsartifacts_manager_kwargsrCconcrete_artifact_cmwrapped_method=/usr/local/lib/python3.10/dist-packages/ansible/cli/galaxy.pymethod_wrapperbs&   $z9with_collection_artifacts_manager..method_wrapper) functoolswraps)rUrXrVrTrW!with_collection_artifacts_manager[sr[ c CsBtdj|||dtt||gdtt||g||ddS)Nz) # {0} {1:{cwidth}} {2:{vwidth}} {3} {4} -)cwidthvwidth)displayformatmaxlen)pathh1h2w1w2rVrVrW_display_header|s rjcCs:|j}d}|r |dd}|sd}td|j|fdS)Nversionz(unknown version)z- %s, %s) install_inforIrar@)grrlrkrVrVrW _display_roles rnc Cs0tdjt|j|jt||t||ddS)Nz"{fqcn:{cwidth}} {version:{vwidth}})fqcnrkr_r`)rarbr%roverrc) collectionr_r` min_cwidth min_vwidthrVrVrW_display_collections  rtcCs^t|s|f}dd|D}dd|D}tt|pdgtd}tt|p&dgtd}||fS)NcSh|]}t|jqSrV)r%ro.0crVrVrW z)_get_collection_widths..cSrurV)r%rprvrVrVrWryrzkey)r rdrc) collectionsfqcn_set version_set fqcn_lengthversion_lengthrVrVrW_get_collection_widthssrcCs&tt|}|durt|d|S)Nz% is not a valid signature count value)rematchr ValueError)valuerrVrVrWvalidate_signature_counts rc@s*eZdZUded<ded<eddZdS)RoleDistributionServerzt.Union[GalaxyAPI, None]_apizlist[GalaxyAPI] api_serversc Cs\|jr|jS|jD]}z d|jvr||_Wn Wq ty!Yq w|js+|jd|_|jS)Nv1r)rravailable_api_versions Exception)selfserverrVrVrWapis    zRoleDistributionServer.apiN)__name__ __module__ __qualname____annotations__propertyrrVrVrVrWrs rcseZdZdZdZdZfddZfddZdad d Zdad d Z dad dZ daddZ daddZ daddZ daddZdaddZdaddZdaddZdaddZdadd Zdad!d"Zfd#d$Zfd%d&Zed'd(Zd)d*Zdbd,d-Zd.d/Zedcd1d2Zed3d4Zed5d6Zed7d8Z  ddd9d:Z!d;d<Z"d=d>Z#d?d@Z$e%dadAdBZ&dCdDZ'dEdFZ(e%dadGdHZ)e%dadIdJZ*dKdLZ+dMdNZ,dOdPZ-dQdRZ.dSdTZ/e%dadUdVZ0dWdXZ1dYdZZ2d[d\Z3d]d^Z4d_d`Z5Z6S)erKzCommand 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@ description readme_htmlrelatedsummary_fieldsaverage_aw_compositeaverage_aw_scorer/cs||_d|_t|dkr=|ddvr#d|vr#d|vr#|ddd|_|ddddgkr=td ttj t dg|_ d|_ d|_tt||dS) NF)z-hz--helpz --versionrolerqTr<logina$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_rolerdinsertraerrorrbr%rNGALAXY_TOKEN_PATHsysexitrgalaxy lazy_role_apisuperrK__init__)rrP __class__rVrWrs     zGalaxyCLI.__init__c sFtt|jddtjdd}|jddddd |jd td d gtjd |jddddd |jddddddd|jddtddt |tjdd}|jdddddd d!tjdd}|jd"d#d$|jd%d&d$tjdd}|jd'd(ddd)d*t j d+ d,d-}tjdd}|jd.d/d0tjd1d2t jtjd3|d4tjdd}|jd.d5d6tjd1d2tjd7tjjd8tjdd}|jd9d:ddd;d!|jdd!|jjd?d@dA} d1| _| jdBdCd$} | j|jdD| jdEdFdA} d1| _|j| ||gdG|j| ||gdG|j| ||gdG|j| |gdG|j| |||gdG|j | ||gdG|j!| ||gdG| jdHdId$} | j|j"dD| jdJdFdA} d1| _|j| |||gdG|j#| ||gdG|j$| ||gdG|j | ||gdG|j%| |gdG|j&| ||gdG|j'| ||gdG|j(| |||gdG|j| |||gdGdS)Kz* create an options parser for bin/ansible z7Perform various Role and Collection related operations.)descF)add_helpz-sz--server api_serverzThe Galaxy API server URLdesthelpz --api-versionr;r<)typer>rz--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.)rrrz-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=r{-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}'.)rrrrz--clear-response-cacheclear_response_cachez)Clear the existing server response cache.z --no-cacheno_cachez%Do not use the server response cache.TYPEr)metavarrrqz$Manage an Ansible Galaxy collection.funcCOLLECTION_ACTIONr)parentsrzManage an Ansible Galaxy role. ROLE_ACTION))rrK init_parseropt_helpArgumentParser add_argumentr6argparseSUPPRESSadd_verbosity_optionsrNconfigget_configuration_definitionrI unfrack_pathrPrependListActionrbosrerparseradd_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)rcommonrgithubrdefault_roles_pathrr cache_options type_parserrqcollection_parserr role_parserrrVrWrs               zGalaxyCLI.init_parserNcCs|jd|dd}|j|jd|jddddd |jd d d d ddd|jdddddd|jddddd|jddd dddS) NdownloadPDownload collections and their dependencies as a tarball for an offline install.rrrrPz Collection(s)rq*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)rrrdownload_parserrVrVrWrEs$    zGalaxyCLI.add_download_optionscCs|jdkrdnd}|jd|d|d}|j|jd|jdd d d |d |jd |d||dkr8tjntjd|d i}|dkrKt |d<|jd|fdd| i||dkrl|jddddddt |dS)Nrrqrinitz4Initialize 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) rrrbr execute_initrrNGALAXY_COLLECTION_SKELETONGALAXY_ROLE_SKELETONr capitalizeradd_runtask_options)rrr galaxy_typerobj_name_kwargsrVrVrWrXs4  zGalaxyCLI.add_init_optionscC4|jd|dd}|j|jd|jddddd dS) NremovezDelete roles from roles_path.rrrPzRole(s)r+r)rrexecute_remover)rrr remove_parserrVrVrWrtzGalaxyCLI.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)rrr delete_parserrVrVrWrzszGalaxyCLI.add_delete_optionscCspd}|jdkr d}|jd|d|d}|j|jd|j||d|d |dkr6|jd d d d dddSdS)NrrrqlistzAShow the name and version of each {0} installed in the {0}s_path.rr?)rrrz--format output_format)humanyamljsonr&z-Format to display the list of collections in.)rr>r=r)rrrbr execute_listrr)rrrr list_parserrVrVrWrs   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--authorauthorrrPz Search terms searchtermrr)rrexecute_searchr)rrr search_parserrVrVrWrszGalaxyCLI.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)rrr import_parserrVrVrWrs   zGalaxyCLI.add_import_optionscCs|jd|dd}|j|jd|jddddd|jd d d d d d|jddd|jddd|jddd|jddddS)Nsetupz;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.rsourceSourcerrrrrsecretSecret)rr execute_setupr)rrr setup_parserrVrVrWrs  zGalaxyCLI.add_setup_optionscCr) Ninfoz(View more details about a specific role.rrrPrrzrole_name[,version])rrr)rr execute_infor)rrr info_parserrVrVrWrrzGalaxyCLI.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 t j j tj ttd*|jd+d)t d,d-|tj ttd.dS)/NrqverifywCompare checksums with the collection(s) found on the server and the installed copy. This does not verify dependencies.rrrPrrzVThe 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 --keyringrC.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).r aThe 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).4A space separated list of status codes to ignore during signature verification (for example, NO_PUBKEY FAILURE). Descriptions for the choices can be seen at L(https://github.com/gpg/gnupg/blob/master/doc/DETAILS#general-status-codes).Note: specify these after positional arguments or use -- to separate them. --required-valid-signature-countrDrrrr=--ignore-signature-status-coderErrrrr=r>--ignore-signature-status-codesextendrrrrrrr=r>)rrexecute_verifyrrbrNGALAXY_GPG_KEYRINGr%GALAXY_REQUIRED_VALID_SIGNATURE_COUNTr0rrr,GALAXY_IGNORE_INVALID_SIGNATURE_STATUS_CODESr#rkeys)rrrr verify_parservalid_signature_count_helpignore_gpg_status_helprVrVrWrs@          zGalaxyCLI.add_verify_optionsc s>|jdkrdnd}i}|dkrd|d<d}nd|d<d}|jr$d }d }nd |d }d ||}|jd|d|||d}|j|jd|jd[d|dd||jddddd|d|} | jdddddd|d| jd d!ddd"|dd#} d$} |dkr |jd%d&d'| d(d)|jd*d+d,d-d.|jd/d0dd1d2|jd3d4d5ddd6d|jd7d8t j d9d)|jd:d;dt j dd?d@d2|jdAdBt | t jdC|jdDdEtd?tjjt jttdF|jdGdEtdHdI| t jttdJ|jdKdLdddMddS|jr|jd*dNd,dOd.n |jd*dNd,dPd.tdQtfdRdS|jD} tdTtfdUdS|jD} |jr| sM| r|jd7d8t j dVd)|jd:d;dt j dBz1GalaxyCLI.add_install_options..z--role-file($|=)crfrVrgrh) role_file_rerVrWrkDrlz9The keyring used during collection signature verificationz-gz--keep-scm-meta keep_scm_metazBUse tar instead of the scm archive option when packaging the role.rP)rrrbupperrrexecute_installradd_mutually_exclusive_group_get_default_collection_pathrNrZGALAXY_DISABLE_GPG_VERIFYrr[r0rrrr\r#rr]rcompiler8r)rrrr args_kwargsignore_errors_helpdescription_textrbinstall_parserinstall_exclusiver_r` contains_rcontains_role_filerV)rjrmrWrs                              zGalaxyCLI.add_install_optionscCsH|jd|dd}|j|jd|jddddd d |jd d d dddS)NbuildzMBuild an Ansible collection artifact that can be published to Ansible Galaxy.rrrPrqr.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)rrr build_parserrVrVrWrYs   zGalaxyCLI.add_build_optionscCsZ|jd|dd}|j|jd|jdddd|jd d d d d d|jddtddddS)Npublishz0Publish a collection artifact to Ansible Galaxy.rrrPcollection_pathz.The path to the collection tarball to publish.)rrr3r4r5Tz)Don't wait for import validation results.rz--import-timeoutimport_timeoutrz=The time to wait for the collection import process to finish.)rrr=r)rrexecute_publishrr6)rrrpublish_parserrVrVrWrgs   zGalaxyCLI.add_publish_optionscsZtt||}t|d|jdurdn|j t|d|jdur"|jntj |jt _|S)Nr7rB) rrKpost_process_argssetattrrr7rNGALAXY_IGNORE_CERTS verbosityra)roptionsrrVrWrss  zGalaxyCLI.post_process_argsc stt|t|_ddi}dD]}|tjvr!tj|||<qg}ddtjp+gD}t |ddD]\}t fdd t D}t t |}tjd |tjd }|d } |d } |d pjt} |d} |d} |ddurtjd|d<|d}| rtddd| d| i|d<d|d <| rt| |d|d <n| r| rt| | || d|d <nt| d|d <|||t|jfd|i|q4tjdtjdrtjd} tdd| d| i|d<ttjdd}tjd}tjddur tjdntj}rBtfdd |Dd}|r)|j|n|jt|jd f|t|d||d!|n||_t|jd"krb|jt|jd#tj f|d"||d!|t!d|j|_"tjd$S)%NcSsTd||fd||dgdd||fig||d}|tvr(|t||S)NzThe %s of the %s Galaxy serverzgalaxy_server.%s)sectionr}r@zANSIBLE_GALAXY_SERVER_%s_%s)rinienvrr)rpSERVER_ADDITIONALrJ)rr}r option_type config_defrVrVrWserver_config_defs z(GalaxyCLI.run..server_config_def)rrcSsg|]}|r|qSrVrVrwsrVrVrWrksz!GalaxyCLI.run..r)startc3s(|]\}}}||||fVqdSNrV)rwkreq ensure_type)r server_keyrVrW s&z GalaxyCLI.run.. galaxy_serverr4r9r3r1r5r7rBzAThe specified "api_version" configuration for the galaxy server "zP" is not a public configuration, and may be removed at any time without warning.zv%sz/v%srr2) access_tokenr4r7r9)r3priorityrz[The --api-version is not a public argument, and may be removed at any time without warning.rr:c3s|] }|jkr|VqdSrr@r) cmd_serverrVrWrscmd_arg)r3rr7r:rr=r)#rrKrunr rrrHrNGALAXY_SERVER_LIST enumeratedict SERVER_DEFr(r!get_single_datar+initialize_plugin_configuration_definitionsget_plugin_optionspoprrawarningrrrrJrPr GALAXY_SERVER_TIMEOUTnextrrd GALAXY_SERVERrr)rgalaxy_options optional_keyconfig_servers server_listserver_priority config_dictdefsserver_optionsr4r9 token_valr1r5r7 cmd_tokendefault_server_timeout config_serverr)rrrrWr~s                  z GalaxyCLI.runcCs|jjSr)rrrrVrVrWrsz GalaxyCLI.apicCs tjdS)Nr)rNCOLLECTIONS_PATHSrrVrVrWrs s z&GalaxyCLI._get_default_collection_pathTc sggd}tdd}tj|stdttdt|d'}zt |}Wnt yD} z tdtt| fd} ~ wwWdn1sOwY|dur`td tfd d } t |t r|srtd |D] } |d | | 7<qt|St |t rt|td dg} | rtdtd| |d pgD] } |d | | 7<qfdd|dpgD|d<|Stdt|j)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. )rolesr~surrogate_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|vr*t|}tdt|d|vrd|vrtdtjjfi|gSt |ddd}t j |sDtdt |t ft|d 2}zfd d d d t|DDWWdStyz}z tdt t |fd}~ww1s~wYdS)Nincludezfound role %s in yaml filer@srcz!Must specify name or src for rolerrz5Failed to find include requirements file '%s' in '%s'rcs"g|] }tjjfi|qSrV)rrrrwrrrVrWrkOs"zNGalaxyCLI._parse_requirements_file..parse_role_req..css|]}t|VqdSr)r)role_yaml_parse)rwirVrVrWrPzMGalaxyCLI._parse_requirements_file..parse_role_req..z9Unable to load data from include requirements file: %s %s)r)rravvvr%rrrrr#rreisfiler$openr"r) requirementrb_include_path f_includee)requirements_filerrVrWparse_role_req@s0    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 installrr~z\Expecting only 'roles' and/or 'collections' as base keys in the requirements file. Found: %sz, cs g|] }t|qSrV)rfrom_requirement_dict_init_coll_req_dict)rwcollection_req)rArvalidate_signature_optionsrVrWrkhsz6GalaxyCLI._parse_requirements_file..z?Expecting requirements yaml to be a list or dictionary but got )r#rreexistsrr$rarrr"r isinstancer#rsetr] differencejoinrIrr) rrallow_old_formatrArrb_requirements_filereq_objfile_requirementserrrrole_req extra_keysrV)rArrrrW_parse_requirements_filesT          z"GalaxyCLI._parse_requirements_filecstts diSdvsdrdddkrSttfdd|jDt|jdjdddt j d d d<S) Nr@r>rrc3s(|]}d|j|jhvr|VqdS)r>N)r@r)rwsrvrcoll_reqrVrWrsz0GalaxyCLI._init_coll_req_dict..zexplicit_requirement_{name!s}rrB)r7) rrrIriterrr rrbrrH)rrrVrrWrvs*  zGalaxyCLI._init_coll_req_dictrcCstjds tddS)zn Exits with the specified return code unless the option --ignore-errors was specified rKzR- you can use --ignore-errors to skip failed roles and finish processing the list.N)rrHr)rcrVrVrWexit_without_ignores zGalaxyCLI.exit_without_ignorecCsddt|dg}|di}|d|dd}|d|t|D]@}|tjvr/q't||tr\|d|t||D]}|tjvrMqE|d||||fqEq'|d |||fq'|dd |S) Nr{zRole: %sr@ galaxy_inforz description: %sz %s:z %s: %sz %s: %s ) r%rIrPsortedr]rKSKIP_INFO_KEYSrrr) role_infotextrrrr}rVrVrW_display_role_infos"     zGalaxyCLI._display_role_infocCstjtjtj|Sr)rreabspath expanduser expandvarsrerVrVrWrLszGalaxyCLI._resolve_pathcstt|ddd}t|dd}Wdn1swYt}g}g}|D]9}|ddr4|n|}||dd} | sZ|dd} | dkrMd } n | d krTg} n| d krZi} | |d <||q*td tdfdd} t } t | ||dd} | | j j d<| |}|S)NrrrrFr}rr0r{r#rrzL\(([^)]+),\s+([^)]+)\)z C\(([^)]+)\)csJt|trddd|D}d|}d|}tj|ddddd S) Nz. cSsg|]}|dqSr~)rstrip)rwlrVrVrWrkrzzKGalaxyCLI._get_skeleton_galaxy_yml..comment_ify..z\1 <\2>z'\1'uz# F)widthinitial_indentsubsequent_indentbreak_on_hyphens)rr#rsubtextwrapfill)v const_pattern link_patternrVrW comment_ifys   z7GalaxyCLI._get_skeleton_galaxy_yml..comment_ify)required_configoptional_config variablesr)rr#r%readr rIrPrrur'r* environmentfilterstemplate) template_path inject_data template_obj meta_template galaxy_metarr meta_entry config_listr meta_typerloadertemplar meta_valuerVrrW_get_skeleton_galaxy_ymls6       z"GalaxyCLI._get_skeleton_galaxy_ymlcsp|r|rtd|s|std|r)durtdt|}|j|dd}|Sfdd|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)rrAcsg|] }t|qSrV)r from_string)rw coll_inputrArOrVrWrks zFGalaxyCLI._require_one_of_collections_requirements..)r~r)rrKrLr)rr~rrOrArrVrrW(_require_one_of_collections_requirementss,  z2GalaxyCLI._require_one_of_collections_requirementscCdS)z Perform the action on an Ansible Galaxy role. Must be combined with a further action like delete/install/init as listed below. NrVrrVrVrWrzGalaxyCLI.execute_rolecCr)z Perform the action on an Ansible Galaxy collection. Must be combined with a further action like init/install as listed below. NrVrrVrVrWrrzGalaxyCLI.execute_collectioncCstjd}ttjd}t|dd}tj|st|ntj |r-t dt |tjdD]}t|}t t |ddt |dd|q2dS)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). rrrrz9- the output collection directory %s is a file - abortingrPN)rrHrKrLr#rrermakedirsrrr$rr%)rrr b_output_pathrrVrVrWr!s        zGalaxyCLI.execute_buildcCstjd}tjd}tjd}tjd}|rt|}|j|||dd}t|}t|dd}tj|s;t |t |||j |tjd |dd S) rrPrrrrAr~rrrr) rrHrKrLrr#rrerrrr)rrAr~rrrrb_download_pathrVrVrWr 8s,          zGalaxyCLI.execute_downloadc'sFtjd}tjd}tjd}tjd|}tjd|}td|tdd}|d krR|td d d |tjd ddddtddgd tj}t j ||}n+|dkr}| dd\} } |t| | dddgdgddddgd tj }t j || | }t|dd} t j | rt j |rtdt||std t|t j| d!d"D]'\} } }| D]}t j | |}t|q|D]}t j | |}t |qq|durd#}n d!}|jj}d$g}t j |}d%d&|Dt j |std't||t}|t|t||d(}t j | st | t j|d!d"D]t\} } }t j | | t j}|d)}|dkrF|d*voDd+|v}n|d+k}fd,d&| D| dd<|D]t j \}}t!fd-d.DrrqY|dkr|rȈdkrȈd/kr|"}|#d0|d1<t$%t j | |}tt j ||dd}t&|d2}|'t|ddWdn 1swYqY|d3kr8|s8t j | }t j ||}t(|)|d)dd}z t|*|dd} Wn%ty}!zt| td4|+d5|d6|d7|!|!d}!~!wwt&|d2 }"|"'| Wdn 1s1wYqYt j t j | |}#tj,t j | t j ||#d#d8qY| D]9}$tt j ||$dd}%t j |%rqqZtt j | |$dd}&t j -|&rtj,|&|%d#d8qZt |%qZq t..d9|+|fdS):z 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 ``.``. rr rrrzyour {0} descriptionzplugins/plugins.html)ransible_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<) r.companylicenser7rissue_tracker_urlrepository_urldocumentation_url homepage_urlmin_ansible_version dependenciesrqrrz1.0.0z README.mdzyour name zGPL-2.0-or-later) namespacecollection_namerkreadmeauthorsr$ repository documentationhomepageissues build_ignorerrz6- 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|qSrV)rru)rwxrVrVrWrkrzz*GalaxyCLI.execute_init..z9- the skeleton path '{0}' does not exist, cannot init {1}rr) playbooksr templatescs&g|]tfddDsqS)c3|]}|VqdSrrgrdrVrWrrz4GalaxyCLI.execute_init...)any)rw)skeleton_ignore_rer9rWrks&c3s$|] }|tjVqdSr)rrrerr)frel_rootrVrWrs"z)GalaxyCLI.execute_init..z galaxy.yml.j2r,r@wbz.j2zFailed to create  z . Templating z failed with the error: )follow_symlinksz - %s %s was created successfully)/rrHrbrr-rJansible_versionrNGALAXY_ROLE_SKELETON_IGNORErrersplit!GALAXY_COLLECTION_SKELETON_IGNOREr#rrrr$walkshutilrmtreeunlinkrdefault_role_skeleton_pathrr'r.r*rrelpathsepsplitextr;copyrrKrrwriter%_get_file_contentsr titlecopyfileislinkra)'rrr r obj_skeletonobj_namer skeleton_ignore_expressionsobj_pathr+r, b_obj_pathrootdirsfilesold_dirreold_file own_skeletonrrrel_dirs rel_root_dirin_templates_dirfilenameext template_datar b_dest_file galaxy_obj src_template dest_file b_renderedrdf f_rel_pathr: b_dir_path b_src_dirrV)r=r>r<rWrUs               $  &  ( zGalaxyCLI.execute_initc Cs`tjd}d}tjdD]}d|i}t|j|j|}|j}|r1d|vr,|d|d<|d=||tjdsyd}z |j|d }Wn)t yj}z|j d kr^d |j vr^d |}WYd}~nKt d ||fd}~ww|rs||nd |}n0tjdr|j sd |}n"|jr||jt} | d|i} | r|| |||7}q ||dS)zx prints out detailed information about an installed role as well as info available from the galaxy API. rr{rPrerkinstalled_versionrNFiz Bad Request- the role %s was not foundz"Unable to find info about '%s': %sr)rrHrrrrlrJrlookup_role_by_namer http_codemessager_existsmetadatar)rrpager) rrdatarrrmrl remote_datarr role_specrVrVrWrEsJ       zGalaxyCLI.execute_infoc Cstjd}tj}tjd}tjd}tjd}tjd}|dur$t|}|j||||dd}d d |D} t|| |j|||d } td d | DrLdSdS)rHrPrKrrrONrOrAr~cSsg|] }tt|qSrV)rrKrL)rwrerVrVrWrk;rlz,GalaxyCLI.execute_verify..)local_verify_onlyrAcss|]}|js|VqdSr)success)rwresultrVrVrWrDrz+GalaxyCLI.execute_verify..rr) rrHr+collection_pathsr#rrrr;) rrAr~ search_pathsrKrzrrOrresolved_pathsresultsrVrVrWrY(s2     zGalaxyCLI.execute_verifycCstjd}tjd}d}tjd}|durt|}|r!t|}dt|}g}g}tjddkrTttjd}|j||||d } | d }| d rSt | d nz|s^|dur^t d |r| dsn| dsnt d|j} |jo{d| vo{d| v} |j||| d} | d }| d r|jrd| vsd| vr|jrtjntj } | | dn&|}| d }ntjdD]} t| }|t|j|jfi|q|s|stddS|rtd|||rtd|j|||ddSdS)a Install one or more roles(``ansible-galaxy role install``), or one or more collections(``ansible-galaxy collection install``). You can pass in a list (roles or collections) or use the file option listed below (these are mutually exclusive). If you pass in a list, it can be a name (which will be downloaded via the galaxy API and github), or it can be a local tar archive file. rPrNrOzThe requirements file '%s' contains {0}s which will be ignored. To install these {0}s run 'ansible-galaxy {0} install -r' or to install both at the same time run 'ansible-galaxy install -r' without a custom install path.rrqrryr~rrz3- you must specify a user/role name or a roles filez.yamlz.ymlzJInvalid role requirements file, it must end with a .yml or .yaml extensionrr)rArz'Skipping install, no requirements foundz$Starting galaxy role install processz*Starting galaxy collection install processr )rrHrIr#rKrLr%rrarrbr endswithrrrrrrsr)rstriprPrrr_execute_install_role_execute_install_collection)rrA install_itemsrrrOtwo_type_warningcollection_requirementsrole_requirementsr galaxy_argswill_install_collections display_funcrnamerrVrVrWrqIsv           zGalaxyCLI.execute_installcsltjd}tjd}tjd}tjd}ztjd}Wnty*|jr)tdwtjdd} tjd d} tj} td d tjD} td d t j D} tj o^t fd d | D }|rvt fdd | Drvt ddn|rt dttd| ft}t|dd}tj|st|t|||j||||| | ||tjdd| d dS)NrrKrrcrezUnable to properly parse command line arguments. Please use "ansible-galaxy collection install" instead of "ansible-galaxy install".rFrdcs|]}t|VqdSrrrwprVrVrWrz8GalaxyCLI._execute_install_collection..csrrrrrVrVrWrrc3r8r startswithrrrVrWrrc3r8rrrrrVrWrrz The specified collections path 'z' appears to be part of the pip Ansible package. Managing these directly with ansible-galaxy could break the Ansible package. Install collections to a configured collections path, which will take precedence over collections found in the PYTHONPATH.zThe 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.:rrr)rrArerread_requirement_pathsr)rrHKeyErrorrrrIrNrrr+r}GALAXY_COLLECTIONS_PATH_WARNINGr;rarr%rrr#rrerrrr)rrrerArrKrrcrerrdr managed_pathsread_req_pathsunexpected_pathrrrVrrWrsR             z%GalaxyCLI._execute_install_collectionc Cstjd}tjd}tjd}tjdp|}|D]U}|r3tjdr3|jtjdvr3td|jqtd|j|jdur|jd|jksJ|rt|rbtd |j|jd|jpYd f|ntd |j|jd|jpod fq|std t |qz| }Wn"t y}ztd |jt |f| WYd}~qd}~ww|s_|r_|jstd|jn|j|j} | D]} td| t} | | } t|j|jfi| } d| jvrd| jvr| jdurq| jdur| |vr tdt | || qtd| jq| jd| jkrM|r:td| j| jd| jp,d f| || qtdt | | j|j| jdfq|rV|| qtd| jq|sntd|j| qdS)NrrrcrrPzSkipping role %szProcessing role %s rkz - 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 %srz- 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)rrHr@rarrlrkrrr0rarr%rrtremetadata_dependenciesrdebugr)rrrrrscmrP)rr role_filer force_depsrr installedrrole_dependenciesdepdep_reqdep_infodep_rolerVrVrWrs                zGalaxyCLI._execute_install_rolec Cstjds tdtjdD]5}t|j|j|}z|r%td|ntd|WqtyC}z t d|t |fd}~wwdS)zV removes the list of roles passed as arguments from the local system. rPz/- you must specify at least one role to remove.z- successfully removed %sz - %s is not installed, skipping.zFailed to remove role %s: %sNr) rrHr rrrrrarrr$)rr7rrrVrVrWr-s zGalaxyCLI.execute_removecCs8tjddkr |dStjddkr|dSdS)z5 List installed collections or roles rrrqN)rrHexecute_list_roleexecute_list_collectionrrVrVrWr)As   zGalaxyCLI.execute_listc Csxd}d}g}tjd}tjd}|D]}t|}tj|r"d}n |d|q|r_t |j |j |tj ||d}tj|jrWd}t dtj|jt|nG|d|qtj|sm|d |qtj|s{|d |qt d|t|} | D]} t |j |j | |d}|jrt|qq|r|rg}|D]} t | q|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# %sroz(- 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)rrHrKrLrreisdirrPrbrrrrradirnamernrlistdirrtrr ) r path_found role_foundwarningsroles_search_pathsr7re role_pathrm path_files path_filewrVrVrWrKsT        zGalaxyCLI.execute_list_rolecCs |durd|_tjd}tjd}ttj}ttjdpg|BttjB}i}g}d}d} d} d} |r?t|| d\} } t t t ||| | dd} t} t | \}}t | dd d D]<}d } tt|jjj}|d vr||id |ji|||j<q]|| vrt|dd||| |t|||q]d}|D]-}tj|s||vrq|d|qtj|rtj|s|d|qd }q| r|rg}|D]}t !|q| s|st"dtjd|dkrt t#$|dS|dkrt t%|dS)zz List all collections installed on the local system :param artifacts_manager: Artifacts manager. NFr%rqrr)namespace_filtercollection_filterdedupecSs|jSr)r)rxrVrVrWsz3GalaxyCLI.execute_list_collection..r|T>r(r'rk CollectionVersionrz=- the configured path {0}, exists, but it is not a directory.rrr(r'r)&require_build_metadatarrHrrNrr+r}rrDr#rrrpathlibPathr%rparentas_posix setdefaultrprorjaddrtrrerrPrbrrarr r(dumpsr!)rrAr%r,default_collections_pathcollections_search_pathscollections_in_pathsrrcollection_foundrrr~seen fqcn_width version_widthrqrrerrVrVrWrs         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. rPr4rN)rKrLrrHrr)rrr4r:rVrVrWrs  zGalaxyCLI.execute_publishc Cs|d}d}tjdrdtjd}|s&tjds&tjds&tjds&td|jj|tjdtjdtjd|d }|d d krGtd d Sd g}|d |kr\|d|d |fn |d|d g}|dD]}|t |dd|dqkt |}d|}|d ||d||d|dD]}||d|d|df|dfqd|}| |d S)z0 searches for roles on the Ansible Galaxy serveriNrPrr,r-r.zYInvalid query. At least one search term, platform, galaxy tag or author must be provided.)r,tagsr. page_sizecountrzNo roles match your search.r{z6Found %d roles matching your search. Showing first %s.z$Found %d roles matching your search:rr1rr@z %%-%ds %%s)Name Description)z----z -----------%s.%srr) rrHrrr search_rolesrarrPrdrcru) rrr+responservmax_lenrname_len format_strrVrVrWr0s: "       (  zGalaxyCLI.execute_searchc Cs$dtjtjtjtjd}ttjddd}ttjddd}d}tjdr.|jj||d }n|jj ||tjd tjd d }t |d krt j d||fddt j dtj d|D]}t j d|ddd|dddftj dqYt j d||ftj d|St d|ddtjdst d|ddddt d|dd|ddftjdstjdrg}d}|s|jj|ddd}|dddD]} | d|vrt j | d || d!d| | dq|dd"} d#vr d$d%g| }d&}ntd'|r|S)(z+ used to import a role into Ansible Galaxy normal)INFOWARNINGERRORSUCCESSFAILEDrrrrrr8)rrr6r7)r6r7rzEWARNING: More than one Galaxy role associated with Github repo %s/%s.yellowcolorz.The following Galaxy roles are being updated: rrrr+r@z[ To properly namespace this role, remove each of the above and re-import %s/%s from scratchz(Successfully submitted import request %didr4z Role name: %sz Repo: %s/%sF)task_id task_messages message_text message_typestate)rrrrTr\)rN COLOR_WARN COLOR_ERRORCOLOR_OKr%rrHrget_import_taskcreate_import_taskrdra COLOR_CHANGEDrPindextimesleep) rcolorsrrrtasktmsg_listfinishedmsgrrVrVrWr9s\   2 "   zGalaxyCLI.execute_importcCstjdrD|j}t|dkrtddStjdtjdtjdtjd|D]}tjd|d|d |d |d ftjdq)dStjd 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/%srr>rrr<zDSecret removed. Integrations using this secret will not longer work.r@zAdded integration for %s %s/%s) rrHr list_secretsrdrarNr remove_secret add_secret)rsecretsr@r>rrresprVrVrWrBKs2          zGalaxyCLI.execute_setupcCstjd}tjd}|j||}t|ddkrs       ,                  !     C