o
    !dD                     @   s   d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZ d dl	m
Z
 d dlmZmZ d dlmZ dZdZd	ZG d
d deZG dd dZG dd dZG dd dZdS )    N)compatconfig)ClientError)compat_open)
exceptionsfilehelpers)BasicCommand
      ih  c                	   @   s   e Zd ZdZdZddddddddd	d
ddddddddddddddgZdZdZdZdZ	dd Z
dd Zdd Zdd Zdd Zd d! Zd"d# Zd$S )%	ECSDeployZdeploya  Deploys a new task definition to the specified ECS service. Only services that use CodeDeploy for deployments are supported. This command will register a new task definition, update the CodeDeploy appspec with the new task definition revision, create a CodeDeploy deployment, and wait for the deployment to successfully complete. This command will exit with a return code of 255 if the deployment does not succeed within 30 minutes by default or up to 10 minutes more than your deployment group's configured wait time (max of 6 hours).servicezJThe short name or full Amazon Resource Name (ARN) of the service to updateT)nameZ	help_textrequiredztask-definitionzThe file path where your task definition file is located. The format of the file must be the same as the JSON output of: <codeblock>aws ecs register-task-definition --generate-cli-skeleton</codeblock>codedeploy-appspeca  The file path where your AWS CodeDeploy appspec file is located. The appspec file may be in JSON or YAML format. The <code>TaskDefinition</code> property will be updated within the appspec with the newly registered task definition ARN, overwriting any placeholder values in the file.clusterzThe short name or full Amazon Resource Name (ARN) of the cluster that your service is running within. If you do not specify a cluster, the "default" cluster is assumed.Fzcodedeploy-applicationzThe name of the AWS CodeDeploy application to use for the deployment. The specified application must use the 'ECS' compute platform. If you do not specify an application, the application name <code>AppECS-[CLUSTER_NAME]-[SERVICE_NAME]</code> is assumed.zcodedeploy-deployment-groupa*  The name of the AWS CodeDeploy deployment group to use for the deployment. The specified deployment group must be associated with the specified ECS service and cluster. If you do not specify a deployment group, the deployment group name <code>DgpECS-[CLUSTER_NAME]-[SERVICE_NAME]</code> is assumed.z6Successfully registered new ECS task definition {arn}
z%Successfully created deployment {id}
z8Successfully deployed {task_def} to service '{service}'
zcustomization/ecs-deployc                 C   s   |  |j|j\}}t| j||| j}| ||| _| jjd|j	|j
tj| jdd}| | | j | _| ||| _| || d S )NZ
codedeployuser_agent_extra)region_nameverifyr   )_load_file_argsZtask_definitionZcodedeploy_appspec	ECSClientZ_sessionUSER_AGENT_EXTRA_get_resource_names	resourcescreate_clientregion
verify_sslr   Config_validate_code_deploy_resources_cd_validatorget_deployment_wait_time	wait_time_register_task_deftask_def_arn_create_and_wait_for_deployment)selfparsed_argsparsed_globalsregister_task_def_kwargsappspec_objZecs_client_wrapperZcodedeploy_client r*   Dusr/lib/python3.10/site-packages/awscli/customizations/ecs/deploy.py	_run_mainr   s,   
zECSDeploy._run_mainc                 C   s   t ||}|| j || jd | jd }tj| jj	|d |
|| j | jd }tj| jj	| j|d tj  d S )Napp_namedeployment_group_name)idr   )Ztask_defr   )CodeDeployerupdate_task_def_arnr#   create_deploymentr   sysstdoutwriteMSG_CREATED_DEPLOYMENTformatwait_for_deploy_successr!   MSG_SUCCESSflush)r%   clientZappspecZdeployerdeployment_idservice_namer*   r*   r+   r$      s"   

z)ECSDeploy._create_and_wait_for_deploymentc              
   C   sz   t jt j|}zt|}| W  d    W S 1 sw   Y  W d S  tttfy< } zt	j
||dd }~ww )N)	file_patherror)ospath
expandvars
expanduserr   readOSErrorIOErrorUnicodeDecodeErrorr   ZFileLoadError)r%   r>   	full_pathfer*   r*   r+   _get_file_contents   s   
(zECSDeploy._get_file_contentsc                 C   sR   |  }|d }|d }t|||j}t|||j}||d ||d ||dS )Nr=   cluster_nameservice_arncluster_arn)r   rM   r   rN   r-   r.   )get_service_detailsr   Zget_app_nameZcodedeploy_applicationZget_deploy_group_nameZcodedeploy_deployment_group)r%   args
ecs_clientservice_detailsr=   rL   Zapplication_namer.   r*   r*   r+   r      s    zECSDeploy._get_resource_namesc                 C   s0   |  |}t|}|  |}t|}||fS N)rK   jsonloadsr   Zparse_appspec)r%   Ztask_def_argZappspec_argZtask_def_stringr(   Zappspec_stringr)   r*   r*   r+   r      s
   



zECSDeploy._load_file_argsc                 C   s:   | |}|d d }tj| jj|d tj  |S )NtaskDefinitionZtaskDefinitionArn)Zarn)register_task_definitionr3   r4   r5   MSG_TASK_DEF_REGISTEREDr7   r:   )r%   Ztask_def_kwargsrQ   responser#   r*   r*   r+   r"      s   

zECSDeploy._register_task_defc                 C   s&   t || j}|  |  || _d S rS   )CodeDeployValidatorr   describe_cd_resourcesvalidate_allr   )r%   r;   	validatorr*   r*   r+   r      s   
z)ECSDeploy._validate_code_deploy_resourcesN)__name__
__module____qualname__NAMEZDESCRIPTIONZ	ARG_TABLErX   r6   r9   r   r,   r$   rK   r   r   r"   r   r*   r*   r*   r+   r      sR    
	<		r   c                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )r0   zKWaiting for {deployment_id} to succeed (will wait up to {wait} minutes)...
c                 C      || _ || _d S rS   )_client_appspec_dict)r%   	cd_clientZappspec_dictr*   r*   r+   __init__      
zCodeDeployer.__init__c              
   C   sP   |  ||}z| jjdi |}W |d S  ty' } ztjd|dd }~ww )Nzcreate deploymentactionr?   deploymentIdr*   )_get_create_deploy_requestrc   r2   r   r   ServiceClientError)r%   r-   deploy_grp_nameZrequest_objrY   rJ   r*   r*   r+   r2      s   zCodeDeployer.create_deploymentc                 C   s$   t | j}t|}t| S rS   )rT   dumpsrd   r   Zensure_byteshashlibsha256	hexdigest)r%   Zappspec_strZappspec_encodedr*   r*   r+   _get_appspec_hash   s   
zCodeDeployer._get_appspec_hashc                 C   s$   ||dt | j|  dddS )NZAppSpecContent)contentrp   )ZrevisionTypeZappSpecContent)applicationNamedeploymentGroupNamerevision)rT   rn   rd   rr   )r%   r-   rm   r*   r*   r+   rk      s   
z'CodeDeployer._get_create_deploy_requestc                 C   s   | j }td|d}g }|| D ]&}|D ]}|| }t||d}|| }	t||	d}
||	|
< q|| q|||< || _ dS )a  
        Inserts the ARN of the previously created ECS task definition
        into the provided appspec.

        Expected format of ECS appspec (YAML) is:
            version: 0.0
            resources:
              - <service-name>:
                  type: AWS::ECS::Service
                  properties:
                    taskDefinition: <value>  # replace this
                    loadBalancerInfo:
                      containerName: <value>
                      containerPort: <value>
        r   r   Z
propertiesrV   N)rd   r   Zfind_required_keyappend)r%   Znew_arnr)   Zresources_keyZupdated_resourcesresourcer   Zresource_contentZproperties_keyZproperties_contentZtask_def_keyr*   r*   r+   r1      s&   

z CodeDeployer.update_task_def_arnc                 C   sn   | j d}|d ur|tkrt}n
|d u s|dk rd}t}|d | }||d}| || |j||d d S )NZdeployment_successful   <   )ZDelayZMaxAttempts)rj   ZWaiterConfig)rc   Z
get_waiterMAX_WAIT_MINDEFAULT_DELAY_SEC_show_deploy_wait_msgwait)r%   r/   wait_minwaiterZ	delay_secZmax_attemptsr   r*   r*   r+   r8   (  s   z$CodeDeployer.wait_for_deploy_successc                 C   s&   t j| jj||d t j  d S )N)r<   r~   )r3   r4   r5   MSG_WAITINGr7   r:   )r%   r/   r   r*   r*   r+   r}   ;  s   z"CodeDeployer._show_deploy_wait_msgN)r^   r_   r`   r   rf   r2   rr   rk   r1   r8   r}   r*   r*   r*   r+   r0      s    +r0   c                   @   s<   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd ZdS )rZ   c                 C   rb   rS   )rc   _resource_names)r%   re   r   r*   r*   r+   rf   C  rg   zCodeDeployValidator.__init__c              
   C   s   z| j j| jd d| _W n ty  } ztjd|dd }~ww z| jd }| jd }| j j||d| _W d S  tyJ } ztjd|dd }~ww )Nr-   )rt   z describe Code Deploy applicationrh   r.   )rt   ru   z%describe Code Deploy deployment group)	rc   Zget_applicationr   app_detailsr   r   rl   Zget_deployment_groupdeployment_group_details)r%   rJ   dgpZappr*   r*   r+   r[   G  s,   

z)CodeDeployValidator.describe_cd_resourcesc                 C   sV   t | dr
| jd u rd S | jd }|d }|d d }d}|| d }|| }|t S )Nr   deploymentGroupInfoZ blueGreenDeploymentConfigurationZdeploymentReadyOptionZwaitTimeInMinutesZ)terminateBlueInstancesOnDeploymentSuccessZterminationWaitTimeInMinutes)hasattrr   TIMEOUT_BUFFER_MIN)r%   Zdgp_infoZblue_green_infoZdeploy_ready_wait_minZterminate_keyZtermination_wait_minZconfigured_waitr*   r*   r+   r    X  s   




z,CodeDeployValidator.get_deployment_wait_timec                 C   s   |    |   d S rS   )validate_applicationvalidate_deployment_group)r%   r*   r*   r+   r\   l  s   z CodeDeployValidator.validate_allc                 C   s.   | j d }| jd d dkrtjd|dd S )Nr-   ZapplicationcomputePlatformECSZApplicationrx   r   )r   r   r   InvalidPlatformError)r%   r-   r*   r*   r+   r   p  s   
z(CodeDeployValidator.validate_applicationc                 C   s   | j d }| j d }| j d }| j d }| j d }| jd }|d }|dkr-tjd	|d
| jd d }|D ]*}	|	d }
|
|krL|
|krLtj|d|d|	d }||kr`||kr`tj|d|dq6d S )Nr.   r   rM   r   rN   r   r   r   zDeployment Groupr   ZecsServicesserviceName)Zdg_namerx   resource_nameZclusterName)r   r   r   r   ZInvalidProperyError)r%   r   r   rM   r   rN   Zgrp_infoZcompute_platformZtarget_servicestargetZtarget_servZtarget_clusterr*   r*   r+   r   v  s4   





z-CodeDeployValidator.validate_deployment_groupN)	r^   r_   r`   rf   r[   r    r\   r   r   r*   r*   r*   r+   rZ   B  s    rZ   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )r   c                 C   s6   || _ tj|d| _|jd|j|j|j| jd| _d S )Nr   Zecs)r   endpoint_urlr   r   )	_argsr   r   Z_custom_configr   r   r   r   rc   )r%   Zsessionr&   r'   r   r*   r*   r+   rf     s   zECSClient.__init__c              
   C   s   | j j}|d u s	nd}z| jj|| j jgd}W n ty+ } ztjd|dd }~ww t|d dkr=tj	| j j|d|d d }t
|d	 }|d
 |d |d	 |dS )N default)r   serviceszdescribe ECS servicerh   r   r   )r   r   Z
clusterArnZ
serviceArnr   )rM   r=   rN   rL   )r   r   rc   Zdescribe_servicesr   r   r   rl   lenZInvalidServiceErrorr   Zget_cluster_name_from_arn)r%   r   Zservice_responserJ   rR   rL   r*   r*   r+   rO     s6   


zECSClient.get_service_detailsc              
   C   s@   z| j jdi |}W |S  ty } ztjd|dd }~ww )Nzregister ECS task definitionrh   r*   )rc   rW   r   r   rl   )r%   kwargsrY   rJ   r*   r*   r+   rW     s   z"ECSClient.register_task_definitionN)r^   r_   r`   rf   rO   rW   r*   r*   r*   r+   r     s    
r   )ro   rT   r@   r3   Zbotocorer   r   Zbotocore.exceptionsr   Zawscli.compatr   Zawscli.customizations.ecsr   r   Zawscli.customizations.commandsr   r   r|   r{   r   r0   rZ   r   r*   r*   r*   r+   <module>   s"    9lR