
    VhG                     4   d dl mZmZmZ eZdZdZdZd dl	Z	d dl
Z
d dlZ	 d dlZd dlZd dlZd dlmZ dZdZd d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d Z  G d de!      Z"d Z#d Z$e%dk(  r e$        yy# e$ r  ej(                         ZdZY `w xY w)    )absolute_importdivisionprint_functiona  
module: copr
short_description: Manage one of the Copr repositories
version_added: 2.0.0
description: This module can enable, disable or remove the specified repository.
author: Silvie Chlupova (@schlupov) <schlupov@redhat.com>
requirements:
  - dnf
  - dnf-plugins-core
notes:
  - Supports C(check_mode).
extends_documentation_fragment:
  - community.general.attributes
attributes:
  check_mode:
    support: full
  diff_mode:
    support: none
options:
  host:
    description: The Copr host to work with.
    default: copr.fedorainfracloud.org
    type: str
  protocol:
    description: This indicate which protocol to use with the host.
    default: https
    type: str
  name:
    description: Copr directory name, for example C(@copr/copr-dev).
    required: true
    type: str
  state:
    description:
      - Whether to set this project as V(enabled), V(disabled), or V(absent).
    default: enabled
    type: str
    choices: [absent, enabled, disabled]
  chroot:
    description:
      - The name of the chroot that you want to enable/disable/remove in the project, for example V(epel-7-x86_64). Default
        chroot is determined by the operating system, version of the operating system, and architecture on which the module
        is run.
    type: str
  includepkgs:
    description: List of packages to include.
    required: false
    type: list
    elements: str
    version_added: 9.4.0
  excludepkgs:
    description: List of packages to exclude.
    required: false
    type: list
    elements: str
    version_added: 9.4.0
a  
- name: Enable project Test of the user schlupov
  community.general.copr:
    host: copr.fedorainfracloud.org
    state: enabled
    name: schlupov/Test
    chroot: fedora-31-x86_64

- name: Remove project integration_tests of the group copr
  community.general.copr:
    state: absent
    name: '@copr/integration_tests'

- name: Install Caddy
  community.general.copr:
    name: '@caddy/caddy'
    chroot: fedora-rawhide-{{ ansible_facts.architecture }}
    includepkgs:
      - caddy
an  
repo_filename:
  description: The name of the repo file in which the copr project information is stored.
  returned: success
  type: str
  sample: _copr:copr.fedorainfracloud.org:group_copr:integration_tests.repo

repo:
  description: Path to the project on the host.
  returned: success
  type: str
  sample: copr.fedorainfracloud.org/group_copr/integration_tests
N)ConfTF)respawn)	HTTPError)missing_required_lib)distro)AnsibleModule)open_urlc                      t        j                         ry d} t        j                  | d      }|rt        j                  |       y y )N)z/usr/libexec/platform-pythonz/usr/bin/python3z/usr/bin/python2z/usr/bin/pythondnf)r   has_respawnedprobe_interpreters_for_modulerespawn_module)system_interpretersinterpreters     j/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/copr.py_respawn_dnfr   ~   sD     778KUSK{+     c                       e Zd ZdZdZddZed        Zed        Zed        Z	ed        Z
ed        Zed	        Zed
        Zd Zd ZddZd ZddZd Zd Zd Zd Zd Zed        Zed        Zed        Zy)
CoprModulezThe class represents a copr module.

    The class contains methods that take care of the repository state of a project,
    whether the project is enabled, disabled or missing.
    Nc                     || _         || _        || _        || _        || _        || _        |s| j                         | _        y || _        | j                          y N)hostnamestatechrootprotocol
check_modechroot_confget_base)selfr   r   r   r   r   r    s          r   __init__zCoprModule.__init__   sO    		
 $**,DK DKMMOr   c                 @    | j                   j                  dd      d   S )zPstr: Chroot (distribution-version-architecture) shorten to distribution-version.-   r   )r   rsplitr#   s    r   short_chrootzCoprModule.short_chroot   s      {{!!#q)!,,r   c                 B    | j                   j                  d      }|d   S )zstr: Target architecture.r&   )r   split)r#   chroot_partss     r   archzCoprModule.arch   s#     {{((-Br   c                 \    | j                  | j                  j                  d      d         S )z8str: Copr user (this can also be the name of the group)./r   )_sanitize_usernamer   r-   r)   s    r   userzCoprModule.user   s'     &&tyys';A'>??r   c                 >    | j                   j                  d      d   S )z"str: The name of the copr project.r1   r'   )r   r-   r)   s    r   projectzCoprModule.project   s     yys#A&&r   c                 V    t        j                         dk7  r| j                  d       yy)z$Check if the module was run as root.r   z/This command has to be run under the root user.N)osgeteuidraise_exceptionclss    r   	need_rootzCoprModule.need_root   s&     ::<1 QR r   c                     t         j                  j                  j                  t                     | _        | j                  S )zoInitialize the configuration from dnf.

        Returns:
            An instance of the BaseCli class.
        )r   cliBaseClir   baser:   s    r   r"   zCoprModule.get_base   s)     77;;&&tv.xxr   c                 j    | j                   r| j                   j                  |d      t        |      )zRaise either an ansible exception or a python exception.

        Args:
            msg: The message to be displayed when an exception is thrown.
        F)msgchanged)ansible_module	fail_json	Exception)r;   rB   s     r   r9   zCoprModule.raise_exception   s3     $$..3.FFnr   c                 P   d}dj                  | j                  | j                  | j                  || j                        }	 t        |      }|j                         }|j                         j                  d      }||fS # t        $ r}|j                         }Y d}~||fS d}~ww xY w)zSend a get request to the server to obtain the necessary data.

        Args:
            chroot: Chroot in the form of distribution-version.

        Returns:
            Info about a repository and status code of the get request.
        Nz.{0}://{1}/coprs/{2}/repo/{3}/dnf.repo?arch={4}zutf-8)
formatr   r   r   r/   r   getcodereaddecoder   )r#   r   	repo_infourlrstatus_codees          r   _getzCoprModule._get   s     	>EEMM499dii
	&A))+K0I +%%  	&))+K+%%	&s   :A? ?	B%B  B%c                    | j                   j                  dd      \  }}| j                   }	 | j                  |      \  }}|r|S |dk(  rd}d}n}|dk(  r#|dk(  rd}n|dk(  rd	}d
j                  |      }d}nUt	        |      dk7  r| j                  d       n5| j                  dj                  | j                  | j                               )zsDownload information about the repository.

        Returns:
            Information about the repository.
        r&   r'   rhelzcentos-stream-8centoszstream-88zstream-99zepel-{0}epel404zIThis repository does not have any builds yet so you cannot enable it now.z Chroot {0} does not exist in {1})r*   r-   rQ   rH   strr9   r   r   )r#   distributionversionr   rL   rO   s         r   _download_repo_infozCoprModule._download_repo_info   s     !% 1 1 7 7Q ?g""%)YYv%6"I{  v%*')j(!G
*!G#**73%{#u,((c ((:AA$++tyyY) r   c                    |s| j                         }| j                  j                  d   rKdj                  | j                  j                  d         }|j	                  d      dj                  |      z   }| j                  j                  d   rKdj                  | j                  j                  d         }|j	                  d      dj                  |      z   }| j                  ||      ry| j                  s}t        |d      5 }|j                  |       d	d	d	       t        j                  |t        j                  t        j                  z  t        j                  z  t        j                   z         y
# 1 sw Y   axY w)a3  Write information to a repo file.

        Args:
            repo_filename_path: Path to repository.
            repo_content: Repository information from the host.

        Returns:
            True, if the information in the repo file matches that stored on the host,
            False otherwise.
        includepkgs,
z
includepkgs={0}
excludepkgsz
excludepkgs={0}
Fzw+NT)r\   rD   paramsjoinrstriprH   _compare_repo_contentr    openwriter7   chmodstatS_IRUSRS_IWUSRS_IRGRPS_IROTH)r#   repo_filename_pathrepo_contentincludepkgs_valueexcludepkgs_valuefiles         r   _enable_repozCoprModule._enable_repo  sB    335L%%m4 #)<)<)C)CM)R S'..t47L7S7STe7ffL%%m4 #)<)<)C)CM)R S'..t47L7S7STe7ffL%%&8,G($/ )4

<()HH"DLL4<<$?$,,$NQUQ]Q]$] ) )s   E88Fc                    dj                  | j                  | j                        }|| j                  j                  v rd| j                  j                  |   j
                  v rp| j                  j                  |   j
                  j                  d      d   }	 |j                  dd      d   j                  dd      d   }|| j                  k7  ry	|S y	# t        $ r |cY S w xY w)
z*Try to get a repository with the old name.z{0}-{1}_coprr1   r,   :   r   r'   N)
rH   r3   r5   r@   reposrepofiler-   r(   r   
IndexError)r#   repo_id	file_namecopr_hostnames       r   _get_repo_with_old_idz CoprModule._get_repo_with_old_id$  s    ""499dll;diioo%'TYY__W5M5V5V*V		099??DRHI! ) 0 0a 8 ; A A#q I! L DII-     !  !s   7C C C#"C#c                    t         j                  j                  j                  | j                  j                  d      }|D ]`  }	 |r6|j
                  |k(  rL| j                  j                  j                  |        y| j                  j                  j                  |       b y# t         j                  j                  $ r$}| j                  t        |             Y d}~d}~ww xY w)zThe method is used to initialize the base variable by
        repositories using the RepoReader class from dnf.

        Args:
            repo_id: Repo id of the repository we want to work with.
        N)r   confrJ   
RepoReaderr@   idrx   add
exceptionsConfigErrorr9   rY   )r#   r{   readerreporP   s        r   _read_all_reposzCoprModule._read_all_repos2  s     ))$))..$? 		-D-ww')		++D1IIOO''-		- >>-- -$$SV,,-s   6B%=%B%%C&C!!C&c                     dj                  | j                  | j                  | j                        }|| j                  j
                  vr| j                         y| j                  j
                  |   S )zReturn one specific repository from all repositories on the system.

        Returns:
            The repository that a user wants to enable, disable, or remove.
        copr:{0}:{1}:{2}N)rH   r   r3   r5   r@   rx   r~   )r#   r{   s     r   _get_copr_repozCoprModule._get_copr_repoE  sY     %++DIItyy$,,O$))//)))+3yyw''r   c                    | j                          | j                         }|n| j                  ry| j                  |       | j                  dj	                  | j
                  | j                  | j                               | j                         }|j                  j                         D ]  }| j                         }t        |d      5 }|j                         }ddd       |k7  r| j                  |||      s y| j                  r_| j                  j                  j!                  |j"                  || j                  j                  j$                  ddi        y# 1 sw Y   xY w)zDisable the repository.

        Args:
            repo_filename_path: Path to repository.

        Returns:
            False, if the repository is already disabled on the system,
            True otherwise.
        NTr   rN   Fenabled0)r   r   r    rs   rH   r   r3   r5   cfgsectionsr\   rf   rJ   resolve_differencesr@   r   write_raw_configfilery   substitutions)r#   rn   r   r{   repo_content_apirr   repo_content_files          r   _disable_repozCoprModule._disable_repoQ  s8    	""$<01  !3!:!:499diiQUQ]Q]!^_&&(Dxx((* 	G#779(#. 0$$(IIK!0 $44//%'79K !??		33MM7DIINN,H,H9VYJZ	 0 0s   
EE(	c                    |j                  d      }|j                  d      }|j                  d       d|v ri|j                  d       dj                  |      dj                  |      k(  ry| j                  s't	        j                  |       | j                  ||       y|j                  d       dj                  |      dj                  |      k7  r3| j                  s't	        j                  |       | j                  ||       y)a  Detect differences between the contents of the repository stored on the
        system and the information about the repository on the server.

        Args:
            repo_content_file: The contents of the repository stored on the system.
            repo_content_api: The information about the repository from the server.
            repo_filename_path: Path to repository.

        Returns:
            False, if the contents of the repo file and the information on the server match,
            True otherwise.
        r`   z	enabled=1z	enabled=0 FT)r-   removerc   r    r7   rs   )r#   r   r   rn   repo_file_linesrepo_api_liness         r   r   zCoprModule.resolve_differencesr  s     ,11$7)//5k*/)"";/xx'388O+DD??		,-!!"46FG  "";/xx'388O+DDII01%%&8:JKr   c                    | j                          | j                         }|sy| j                  s!	 t        j                  |j
                         yy# t        $ r$}| j                  t        |             Y d}~yd}~ww xY w)zRemove the required repository.

        Returns:
            True, if the repository has been removed, False otherwise.
        FNT)	r   r   r    r7   r   ry   OSErrorr9   rY   )r#   r   rP   s      r   _remove_repozCoprModule._remove_repo  so     	""$-		$--(   -$$SV,,-s   A 	A?A::A?c                    | j                          t               }dj                  | j                  | j                  | j
                        }dj                  | j                  | j                  | j
                        |d<   ||d<   dj                  | j                  j                  j                  | j                  | j                  | j
                        }| j                  dk(  r&| j                  |      }d|d<   t        |      |d<   |S | j                  d	k(  r&| j                  |      }d	|d<   t        |      |d<   |S | j                  d
k(  r#| j                         }d
|d<   t        |      |d<   |S )zThe method uses methods of the CoprModule class to change the state of the repository.

        Returns:
            Dictionary with information that the ansible module displays to the user at the end of the run.
        z_copr:{0}:{1}:{2}.repoz{0}/{1}/{2}r   repo_filenamez{0}/_copr:{1}:{2}:{3}.repor   rB   r   disabledabsent)r<   dictrH   r   r3   r5   r@   r   get_reposdirr   rs   boolr   r   )r#   r   r   rn   r   r   removeds          r   runzCoprModule.run  sF    	077		499dll[%,,TYY		4<<Pf!.o9@@IINN''DIIt||
 ::"''(:;G$E%L!']E'N  ZZ:%))*<=H%E%L!(^E'N
 	 ZZ8#'')G#E%L!']E'Nr   c                     t         j                  j                  |       syt        | d      5 }|j	                         }ddd       ||k(  S # 1 sw Y   |k(  S xY w)aD  Compare the contents of the stored repository with the information from the server.

        Args:
            repo_filename_path: Path to repository.
            repo_content_api: The information about the repository from the server.

        Returns:
            True, if the information matches, False otherwise.
        FrN   N)r7   pathisfilerf   rJ   )rn   r   rr   r   s       r   re   z CoprModule._compare_repo_content  sY     ww~~01$c* 	,d $			, $444	, $444s   AAc                      t        j                  d      \  } }}t        j                         }dj	                  | ||j
                  j                        S )zObtain information about the distribution, version, and architecture of the target.

        Returns:
            Chroot info in the form of distribution-version-architecture.
        F)full_distribution_namez{0}-{1}-{2})r
   linux_distributionr   r"   rH   r   r/   )rZ   r[   codenamer@   s       r   r!   zCoprModule.chroot_conf  sG     -3,E,E]b,c)w""$##L'499>>JJr   c                 >    | d   dk(  rdj                  | dd       S | S )zModify the group name.

        Args:
            user: User name.

        Returns:
            Modified user name if it is a group name with @.
        r   @z	group_{0}r'   N)rH   )r3   s    r   r2   zCoprModule._sanitize_username  s+     7c>%%d12h//r   )NFr   )__name__
__module____qualname____doc__rD   r$   propertyr*   r/   r3   r5   classmethodr<   r"   r9   rQ   r\   rs   r~   r   r   r   r   r   r   staticmethodre   r!   r2    r   r   r   r      s    N - -    
 @ @ ' ' S S
    &*@:-&
(B>"8 5 5  K K  r   r   c                     t        t        dd      t        dd      t        dd      t        dg dd	      t        d
      t        ddd      t        ddd            } t        | d      }|j                  }t        s*t	                |j                  t        d      t               |t        _	        t        |d   |d   |d   |d   |d   |j                        }|j                         }d}|d   dk(  r'|d   r"|j                  |d   |d   |d   |d   |       |j                  |d   |d   |d   |d          y)zLThe function takes care of the functioning of the whole ansible copr module.rY   zcopr.fedorainfracloud.org)typedefaulthttpsT)r   required)r   r   r   r   )r   choicesr   )r   listF)r   elementsr   )r   r   r   r   r   r^   ra   )argument_specsupports_check_moder   )rB   	exceptionr   r   r   r   r   )r   r   r   r   r   r    zEPlease note that this repository is not part of the main distributionrB   r   r   )rC   rB   r   r   info)rC   rB   r   r   N)r   r   rb   HAS_DNF_PACKAGESr   rE   r	   DNF_IMP_ERRr   rD   r    r   	exit_json)module_argsmodulerb   copr_moduler   r   s         r   
run_moduler     s[   u&AB5'2ut,'HR[\fuuEfuuEK $OF]]F1%8KP &JF^F^Wo
#h$$K OOERDg)#g'Nev0 	 	
 g%L6]O,	  r   c                      t                y)zLaunches ansible Copr module.N)r   r   r   r   mainr     s    Lr   __main__)&
__future__r   r   r   r   __metaclass__DOCUMENTATIONEXAMPLESRETURNri   r7   	tracebackr   dnf.clidnf.repodictdnf.confr   r   r   ImportError
format_excansible.module_utils.commonr   +ansible.module_utils.six.moves.urllib.errorr   ansible.module_utils.basicr	   ansible.module_utilsr
   r   ansible.module_utils.urlsr   r   objectr   r   r   r   r   r   r   <module>r      s    A @7r*
  	 	K
 0 A ; ' 4 .,Z Zz
,^
 zF W  &)&&(Ks   A< <BB