
    VhT                         d dl mZmZmZ e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mZmZmZ d dlmZ d dlmZ d dlmZ d dlmZmZmZ d d	lmZmZ d d
lmZ d dlm Z  d dl!m"Z"  e       Z# G d de      Z$y)    )absolute_importdivisionprint_functiona  
author:
  - Lorin Hochestein (!UNKNOWN)
  - Leendert Brouwer (!UNKNOWN)
name: docker
short_description: Run tasks in docker containers
description:
  - Run commands or put/fetch files to an existing docker container.
  - Uses the Docker CLI to execute commands in the container. If you prefer to directly connect to the Docker daemon, use
    the P(community.docker.docker_api#connection) connection plugin.
options:
  remote_addr:
    description:
      - The name of the container you want to access.
    default: inventory_hostname
    vars:
      - name: inventory_hostname
      - name: ansible_host
      - name: ansible_docker_host
  remote_user:
    description:
      - The user to execute as inside the container.
      - If Docker is too old to allow this (< 1.7), the one set by Docker itself will be used.
    vars:
      - name: ansible_user
      - name: ansible_docker_user
    ini:
      - section: defaults
        key: remote_user
    env:
      - name: ANSIBLE_REMOTE_USER
    cli:
      - name: user
    keyword:
      - name: remote_user
  docker_extra_args:
    description:
      - Extra arguments to pass to the docker command line.
    default: ''
    vars:
      - name: ansible_docker_extra_args
    ini:
      - section: docker_connection
        key: extra_cli_args
  container_timeout:
    default: 10
    description:
      - Controls how long we can wait to access reading output from the container once execution started.
    env:
      - name: ANSIBLE_TIMEOUT
      - name: ANSIBLE_DOCKER_TIMEOUT
        version_added: 2.2.0
    ini:
      - key: timeout
        section: defaults
      - key: timeout
        section: docker_connection
        version_added: 2.2.0
    vars:
      - name: ansible_docker_timeout
        version_added: 2.2.0
    cli:
      - name: timeout
    type: integer
  extra_env:
    description:
      - Provide extra environment variables to set when running commands in the Docker container.
      - This option can currently only be provided as Ansible variables due to limitations of ansible-core's configuration
        manager.
    vars:
      - name: ansible_docker_extra_env
    type: dict
    version_added: 3.12.0
  working_dir:
    description:
      - The directory inside the container to run commands in.
      - Requires Docker CLI version 18.06 or later.
    env:
      - name: ANSIBLE_DOCKER_WORKING_DIR
    ini:
      - key: working_dir
        section: docker_connection
    vars:
      - name: ansible_docker_working_dir
    type: string
    version_added: 3.12.0
  privileged:
    description:
      - Whether commands should be run with extended privileges.
      - B(Note) that this allows command to potentially break out of the container. Use with care!
    env:
      - name: ANSIBLE_DOCKER_PRIVILEGED
    ini:
      - key: privileged
        section: docker_connection
    vars:
      - name: ansible_docker_privileged
    type: boolean
    default: false
    version_added: 3.12.0
N)AnsibleErrorAnsibleFileNotFoundAnsibleConnectionFailure)shlex_quote)string_types)get_bin_path)to_bytes	to_nativeto_text)ConnectionBaseBUFSIZE)Display)	selectors)LooseVersionc                        e Zd ZdZdZdZ fdZed        Zd Z	d Z
d Zd	 Zd
 Zd Zd Zed        Zd Zd fd	Zd fd	Zd Z fdZ fdZ fdZd Z xZS )
Connectionz  Local docker based connections zcommunity.docker.dockerTc                    t        t        | 
  ||g|i | g | _        i | _        d | _        t        | j                  dd      rd| _        d|v r|d   | _	        y 	 t        d      | _	        y # t        $ r t        d      w xY w)N_IS_WINDOWSF)z.ps1z.exe docker_commanddockerz docker command not found in PATH)superr   __init___docker_args_container_user_cache_versiongetattr_shell!module_implementation_preferences
docker_cmdr   
ValueErrorr   )selfplay_context	new_stdinargskwargs	__class__s        n/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/docker/plugins/connection/docker.pyr   zConnection.__init__   s    j$(yR4R6R %'" 4;;u55ID2v%$%56DOG".x"8 G"#EFFGs   A. .Bc                 b    t        j                  dd|       } t        j                  dd|       } | S )Nz[^0-9a-zA-Z.]r   z^v)resub)versions    r+   _sanitize_versionzConnection._sanitize_version   s,    &&)38&&W-    c                    | j                   }dg}| j                  g|z   |z   }t        j                  |t        j                  t        j                        }|j                         \  }}|t        |      ||j                  fS )Nr/   stdoutstderrr   r#   
subprocessPopenPIPEcommunicater   
returncode)r%   cmd_argsold_version_subcommandold_docker_cmdp
cmd_outputerrs          r+   _old_docker_versionzConnection._old_docker_version   so    $$"+//*X58NN^JOOJOO\--/
Cy4c1<<GGr1   c                    | j                   }g d}| j                  g|z   |z   }t        j                  |t        j                  t        j                        }|j                         \  }}|t        |      ||j                  fS )N)r/   --formatz'{{.Server.Version}}'r3   r6   )r%   r<   new_version_subcommandnew_docker_cmdr?   r@   rA   s          r+   _new_docker_versionzConnection._new_docker_version   sm    $$!Q//*X58NN^JOOJOO\--/
Cy4c1<<GGr1   c                    | j                         \  }}}}|dk(  rVt        |d      j                  d      D ]7  }|j                  d      s| j	                  |j                         d         c S  | j                         \  }}}}|r#t        dt        |      dt        |            | j	                  t        |d            S )	Nr   surrogate_or_stricterrors
zServer version:   zDocker version check (z
) failed: )rB   r   split
startswithr0   rG   r   r   )r%   cmdr@   rA   r;   lines         r+   _get_docker_versionzConnection._get_docker_version   s    +/+C+C+E(Zj?
3HIOOPUV C??#5611$**,q/BBC ,0+C+C+E(ZjSVYbcfYghii%%gjAV&WXXr1   c                    | j                  d      }|| j                  v r| j                  |   S t        j                  | j                  ddd|gt        j
                  t        j
                        }|j                         \  }}t        |d      }|j                  dk7  r4t        j                  d	|d
t        |             d| j                  |<   y|j                         xs d}|| j                  |<   |S )z9 Get the default user configured in the docker container remote_addrinspectrD   z{{.Config.User}}r3   rI   rJ   r   z7unable to retrieve default user from docker container:  Nroot)
get_optionr   r7   r8   r#   r9   r:   r   r;   displaywarningstrip)r%   	containerr?   outrA   users         r+   _get_docker_remote_userz"Connection._get_docker_remote_user   s    OOM2	222--i88dooy*FXZcd$.OOJOOM ==?Sc"78<<1OO_bdklodpqr48D&&y1 yy{%g04""9-r1   c           	      P   | j                   g}| j                  r|| j                  z  }|dgz  }| j                  |d| j                  gz  }| j                  d      r| j                  d      j	                         D ]q  \  }}|df|dffD ]?  \  }}t        |t              rt        dj                  |j                         ||             |ddt        |d	
      t        |d	
      fz  gz  }s | j                  d      u|dt        | j                  d      d	
      gz  }| j                  dk7  rEt        | j                        t        d      k  r$t        dj                  | j                              | j                  d      r|dgz  }|d| j                  d      g|z   z  }|S )z Build the local docker exec command to run cmd on remote_host

            If remote_user is available and is supported by the docker
            version we are using, it will be provided to docker exec.
        s   execs   -u	extra_envKeyValuezNon-string {0} found for extra_env option. Ambiguous env options must be wrapped in quotes to avoid them being interpreted. {1}: {2!r}s   -es   %s=%srI   rJ   working_dirs   -wdevz18.06zlProviding the working directory requires Docker CLI version 18.06 or newer. You have Docker CLI version {0}.
privilegeds   --privilegeds   -irT   )r#   r   remote_userrX   items
isinstancer
   r   formatlowerr   docker_versionr   )r%   rP   	local_cmdkvvalwhats          r+   _build_exec_cmdzConnection._build_exec_cmd   s    __%	***IgY	'%!1!122I??;'4::< H1#$e*q'l!; IC%c<86\#VDJJL$<  eX!DY1Z\def  pE  ]F  1G  &G  H  H	H ??=)5%$//-*HQf!ghhI""f,d>Q>Q1RUabjUk1k. CVD//0 
 ??<(/**I 	eT__];<sBB	r1   c                     | j                   d d = | j                  d      xs t        | j                  dd      }|r%| xj                   |j	                  d      z  c_         y y )Ndocker_extra_argsr   rV   )r   rX   r    _play_contextrN   )r%   
extra_argss     r+   _set_docker_argszConnection._set_docker_args  s[     a __%89qWTEWEWYlnp=q
!1!1#!66 r1   c                    | j                          | j                  d      | _        | j                  1| j                  j                  | j                  j                  | _        | j                  d      | _        | j                  dk(  r@| j                  | j                  j                  k7  r| j                  j                  | _        yyy)za initialize for the connection, cannot do only in init since all data is not ready at that point rg   Ncontainer_timeout
   )rw   rX   rg   ru   timeoutr%   s    r+   _set_conn_datazConnection._set_conn_data  s     	??=9#(:(:(F(F(R#11==D ':;<<2$,,$2D2D2L2L"L--55DL #Mr1   c                 :   | j                   s| j                          | j                         | _         | j                   dk(  rt        j	                  d       | j                   dk7  r,t        | j                         t        d      k  rt        d      | j                   S )Nre   z;Docker version number is "dev". Will assume latest version.z1.3z4docker connection type requires docker 1.3 or higher)r   rw   rR   rY   rZ   r   r   r|   s    r+   rl   zConnection.docker_version,  sx     }}!!# 446DM}}& ^_}}&<+FV\I]+]"#YZZ}}r1   c                    | j                   | j                  dk(  s!t        | j                        t        d      k\  r| j                   S d | _         | j                         }|| j	                  d      k7  r=t
        j                  dj                  | j                  | j                  xs d             |S | j                  j                  dkD  r| j                         S y )Nre   z1.7rg   zEdocker {0} does not support remote_user, using container default: {1}?rM   )rg   rl   r   r_   rX   rY   rZ   rj   actual_user_display	verbosity)r%   r   s     r+   _get_actual_userzConnection._get_actual_user9  s    '""f,T=P=P0QUabhUi0i'''#' "::<$//-"@@OO$l%+VD,?,?AQAQAYUY%Z\""]]$$q( //11r1   c                    t         t        |           | j                  sa| j	                          | j                         }t        j                  dj                  |xs d      | j                  d             d| _        yy)z) Connect to the container. Nothing to do z)ESTABLISH DOCKER CONNECTION FOR USER: {0}r   rT   hostTN)
r   r   _connect
_connectedr}   r   rY   vvvrj   rX   )r%   portr   r*   s      r+   r   zConnection._connectN  sr    j$(*!//1KKKDKK#t%+/??=+I   #DO r1   c                 \   | j                          t        t        |   |||       | j	                  | j
                  j                  d|g      }t        j                  dj                  t        |            | j                  d             t        j                  d       |D cg c]  }t        |d       }}t        j                  |t        j                   t        j                   t        j                   	      }t        j                  d
       | j"                  r| j"                  j%                         r|rt'        j&                  |j(                  t&        j*                  t'        j&                  |j(                  t&        j,                        t.        j0                  z         t'        j&                  |j2                  t&        j*                  t'        j&                  |j2                  t&        j,                        t.        j0                  z         t5        j6                         }|j9                  |j(                  t4        j:                         |j9                  |j2                  t4        j:                         d}	 | j"                  j=                  |      s>| j"                  j?                  |      s"|jA                  | jB                        }	|	s*|jE                         \  }
}tG        dtI        |      z         |	D ]m  \  }}|jJ                  |j(                  k(  r|j(                  jM                         }:|jJ                  |j2                  k(  sT|j2                  jM                         }o s*|jE                         \  }
}tG        dtI        |      z         ||z  }| j"                  j=                  |      s| j"                  j?                  |      s"|jO                          | j"                  j=                  |      sP| j"                  j                  d| j
                        }|jP                  jS                  t        |d      dz          t'        j&                  |j(                  t&        j*                  t'        j&                  |j(                  t&        j,                        t.        j0                   z         t'        j&                  |j2                  t&        j*                  t'        j&                  |j2                  t&        j,                        t.        j0                   z         t        j                  d       |jE                  |      \  }
}t        j                  d       t        j                  d       |jT                  |
|fS c c}w # |jO                          w xY w)z" Run a command on the docker host )in_datasudoable-czEXEC {0}rT   r   zopening command with Popen()rI   rJ   stdinr4   r5   z!done running command with Popen()r1   z:timeout waiting for privilege escalation password prompt:
z;privilege output closed while waiting for password prompt:
become_pass)playcontext   
z!getting output with communicate()zdone communicatingzdone with docker.exec_command())+r}   r   r   exec_commandrr   ru   
executablerY   r   rj   r   rX   debugr   r7   r8   r9   becomeexpect_promptfcntlr4   F_SETFLF_GETFLos
O_NONBLOCKr5   r   DefaultSelectorregister
EVENT_READcheck_successcheck_password_promptselectr{   r:   r   r   fileobjreadcloser   writer;   )r%   rP   r   r   rm   ir?   selectorbecome_outputeventsr4   r5   keyeventchunkr   r*   s                   r+   r   zConnection.exec_commandY  s    	j$,S'H,U(($*<*<*G*Gs)ST	K&&wy'9:Q^A_`45HQR1Xa(=>R	R//????	
 	9:;;4;;4468KK%--QXXu}}1UXZXeXe1efKK%--QXXu}}1UXZXeXe1ef 002Hahh	(<(<=ahh	(<(<=M!++33MB4;;KlKlmzK{%__T\\:F!)**+hkt  vC  lD  ,D  E  E&, 4
U;;!((2$%HHMMOE [[AHH4$%HHMMOE	4 !)**+ilu  wD  mE  ,E  F  F!U*M ++33MB4;;KlKlmzK{"  ;;,,];"kk44]PTPbPb4ch{;PQTYYZKK%--QXXu}}1UY[YfYfXf1fgKK%--QXXu}}1UY[YfYfXf1fg9:w/*+78ff--c SH  s   'VCV BV V+c                 Z   t        | j                  dd      rddl}|j                  |      S |j	                  t
        j                  j                        s8t
        j                  j                  t
        j                  j                  |      }t
        j                  j                  |      S )a   Make sure that we put files into a standard path

            If a path is relative, then we need to choose where to put it.
            ssh chooses $HOME but we are not guaranteed that a home dir will
            exist in any given chroot.  So for now we are choosing "/" instead.
            This also happens to be the former default.

            Can revisit using $HOME instead if it is a problem
        r   Fr   N)	r    r!   ntpathnormpathrO   r   pathsepjoin)r%   remote_pathr   s      r+   _prefix_login_pathzConnection._prefix_login_path  sm     4;;u5??;//))"''++6 ggll277;;D77##K00r1   c                    | j                          t        t        |   ||       t        j                  d|d|| j                  d             | j                  |      }t        j                  j                  t        |d            st        dt        |      z        t        |      }t        t        |d      d      5 }t        j                   |j#                               j$                  sd	}nd
}| j'                  | j(                  j*                  dd|dt,        |g      }|D cg c]  }t        |d       }}	 t/        j0                  ||t.        j2                  t.        j2                        }|j9                         \  }}	|j:                  dk7  r;t7        dt        |      dt        |      dt        |      dt        |	            	 ddd       yc c}w # t4        $ r t7        d      w xY w# 1 sw Y   yxY w)z0 Transfer a file from local to docker container zPUT  TO rT   r   rI   rJ   z!file or module does not exist: %srbz count=0r   r   zdd of= bs=r   Cdocker connection requires dd command in the container to put filesr   zfailed to transfer file  to :
rL   N)r}   r   r   put_filerY   r   rX   r   r   r   existsr   r   r   r	   openfstatfilenost_sizerr   ru   r   r   r7   r8   r9   OSErrorr   r:   r;   )r%   in_pathout_pathin_filecountr(   r   r?   r4   r5   r*   s             r+   r   zConnection.put_file  s   j$((;gx8t}?]^**84ww~~hw7LMN%3i6HHJ J x(
 (7+@A4H 	tG88GNN,-55"''););)F)Fdlnuw|N}(~DGKL!HQ'<=LDLj$$TYcYhYhi ]]_NFF||q "$-g$6	(8KYW]M^`ijp`q$s t t !	t 	t M  j"#hiij	t 	ts8   A+H1G$H5G)=AH$H)G>>HH
c                    | j                          t        t        |   ||       t        j                  d|d|| j                  d             | j                  |      }t        j                  j                  |      }| j                  d| j                  d      d||g}|D cg c]  }t        |d       }}t        j                  |t        j                  t        j                  t        j                  	      }|j!                          t#        | j$                  d
d      r&ddl}|j)                  ||j+                  |            }n=t        j                  j)                  |t        j                  j+                  |            }|j,                  dk7  r| j/                  | j0                  j2                  dd|dt4        g      }|D cg c]  }t        |d       }}t7        t        |d      d      5 }		 t        j                  |t        j                  |	t        j                  	      }|j!                         \  }
}|j,                  dk7  rt;        d|d|d|
d|      	 ddd       ||k7  r-t        j<                  t        |d      t        |d             yyc c}w c c}w # t8        $ r t;        d      w xY w# 1 sw Y   ^xY w)z' Fetch a file from container to local. zFETCH r   rT   r   cp:rI   rJ   r   r   Fr   Nr   zdd if=r   wbr   zfailed to fetch file r   r   rL   strict)r}   r   r   
fetch_filerY   r   rX   r   r   r   dirnamer#   r   r7   r8   r9   r:   r    r!   r   r   basenamer;   rr   ru   r   r   r   r   r   rename)r%   r   r   out_dirr(   r   r?   r   actual_out_pathout_filer4   r5   r*   s               r+   r   zConnection.fetch_file  sX   j$*7H=:Q^A_`))'2 ''//(+$//-2PRY'Z\cdCGHa#89HHT$.OOJOOM	4;;u5$kk'6??73KLO ggll7BGG4D4DW4MNO<<1 ''););)F)FbikrNs(tuDGKL!HQ'<=LDLh7LMtT 	wX`n"((Z__08RA "#<<1$&SZ\dflnt'uvv %	w h&IIhx@(8\dBef '; I  M
  n&'lmmn		w 	ws0   *J+J0?K5J569K5K

KKc                 8    t         t        |           d| _        y)z3 Terminate the connection. Nothing to do for DockerFN)r   r   r   r   )r%   r*   s    r+   r   zConnection.close  s    j$%'r1   c                     i | _         y N)r   r|   s    r+   resetzConnection.reset  s
    %'"r1   r   )NF)__name__
__module____qualname____doc__	transporthas_pipeliningr   staticmethodr0   rB   rG   rR   r_   rr   rw   r}   propertyrl   r   r   r   r   r   r   r   r   __classcell__)r*   s   @r+   r   r      s    *)ING8  
	H	HY*+Z76 
 
*	#=.~1$tB*gX 
(r1   r   )%
__future__r   r   r   type__metaclass__DOCUMENTATIONr   r   os.pathr7   r-   ansible.errorsr   r   r   ansible.module_utils.six.movesr	   ansible.module_utils.sixr
   #ansible.module_utils.common.processr   +ansible.module_utils.common.text.convertersr   r   r   ansible.plugins.connectionr   r   ansible.utils.displayr   Cansible_collections.community.docker.plugins.module_utils.selectorsr   Aansible_collections.community.docker.plugins.module_utils.versionr   rY   r    r1   r+   <module>r      sc    C BdL  	   	 V V 6 1 < T T > ) Y Z
)w( w(r1   