o
    xiع                     @  s  d Z ddlm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	Z	ddl
mZ ddlmZ ddlZddl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dlmZ ddlmZm Z m!Z!m"Z"m#Z#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/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z: ddl;m<Z<m=Z= e-ddd ddl>Z>ddl>m?Z? ddl@mAZA ddlBmCZC ddlDmEZE ddlFmGZG ddlHmIZI dd lJmKZK dd!lLmMZM d"ZNd"ZOePeQZRejSTd#ZUejSTd$ZVG d%d& d&e<ZWG d'd( d(e<ZXG d)d* d*e=ZYd]d5d6ZZd^d>d?Z[d_dDdEZ\d`dJdKZ]dadOdPZ^dbdSdTZ_dcdWdXZ`ddd[d\ZadS )ez:Implementation of KubernetesRunner class for wandb launch.    )annotationsN)Iterator)Any)Api)LaunchAgent)AbstractEnvironment)AbstractRegistry)AzureContainerRegistry)LocalRegistry)Status)WANDB_K8S_LABEL_AGENT"WANDB_K8S_LABEL_AUXILIARY_RESOURCEWANDB_K8S_LABEL_MONITORWANDB_K8S_RUN_IDCustomResourceLaunchKubernetesMonitor)recursive_macro_subsanitize_identifiers_for_k8syield_containers)ExponentialBackoffretry_async)
get_module   )
EntryPointLaunchProject)LaunchError)CODE_MOUNT_DIR
LOG_PREFIXMAX_ENV_LENGTHSPROJECT_SYNCHRONOUSget_kube_context_and_api_clientmake_k8s_label_safemake_name_dns_safe   )AbstractRunAbstractRunnerkubernetes_asynciozfKubernetes runner requires the kubernetes package. Please install it with `pip install wandb[launch]`.)required)client)	AppsV1Api)
BatchV1Api)	CoreV1Api)CustomObjectsApi)NetworkingV1Api)V1Secret)ApiException    WANDB_LAUNCH_CODE_PVC_MOUNT_PATHWANDB_LAUNCH_CODE_PVC_NAMEc                   @  sl   e Zd ZdZ			d'd(ddZed)ddZd*ddZd+ddZd,dd Z	d-d!d"Z
d-d#d$Zd-d%d&ZdS ).KubernetesSubmittedRunz)Wrapper for a launched run on Kubernetes.defaultN	batch_apir*   core_apir+   apps_apir)   network_apir-   namestr	namespace
str | NonesecretV1Secret | Noneauxiliary_resource_label_keyreturnNonec	           	      C  s:   || _ || _|| _|| _|| _|| _d| _|| _|| _dS )ae  Initialize a KubernetesSubmittedRun.

        Other implementations of the AbstractRun interface poll on the run
        when `get_status` is called, but KubernetesSubmittedRun uses
        Kubernetes watch streams to update the run status. One thread handles
        events from the job object and another thread handles events from the
        rank 0 pod. These threads updated the `_status` attributed of the
        KubernetesSubmittedRun object. When `get_status` is called, the
        `_status` attribute is returned.

        Arguments:
            batch_api: Kubernetes BatchV1Api object.
            core_api: Kubernetes CoreV1Api object.
            network_api: Kubernetes NetworkV1Api object.
            name: Name of the job.
            namespace: Kubernetes namespace.
            secret: Kubernetes secret.

        Returns:
            None.
        r   N)	r5   r6   r7   r8   r9   r;   _fail_countr=   r?   )	selfr5   r6   r7   r8   r9   r;   r=   r?    rD   ]/home/ubuntu/.local/lib/python3.10/site-packages/wandb/sdk/launch/runner/kubernetes_runner.py__init__^   s    
zKubernetesSubmittedRun.__init__c                 C     | j S )zReturn the run id.r9   rC   rD   rD   rE   id      zKubernetesSubmittedRun.idc              
     s   zF| j jd| j | jdI d H }dd |jD }|s(td| j  W d S | j j|d | jdI d H }|r=t|W S td|  W d S  t	yd } zt
t d	|  W Y d }~d S d }~ww )
Nz	job-name=label_selectorr;   c                 S     g | ]}|j jqS rD   metadatar9   .0pirD   rD   rE   
<listcomp>       z3KubernetesSubmittedRun.get_logs.<locals>.<listcomp>z"Found no pods for kubernetes job: r   r9   r;   zNo logs for kubernetes pod(s): zFailed to get pod logs: )r6   list_namespaced_podr9   r;   itemswandbtermwarnread_namespaced_pod_logr:   	Exception	termerrorr   )rC   pods	pod_nameslogserD   rD   rE   get_logs   s*   

zKubernetesSubmittedRun.get_logsboolc                   sf   	 |   I dH }tt d| j d|j  |jdv rn	tdI dH  q|  I dH  |jdkS )zzWait for the run to finish.

        Returns:
            True if the run finished successfully, False otherwise.
        TNJob 	 status: finishedfailed	preemptedr0   rg   )	
get_statusrY   termlogr   r9   stateasynciosleep_delete_secretrC   statusrD   rD   rE   wait   s   
zKubernetesSubmittedRun.waitr   c                   s(   t | j}|dv r|  I d H  |S )N)stoppedrh   rg   ri   )r   rj   r9   ro   rp   rD   rD   rE   rj      s
   z!KubernetesSubmittedRun.get_statusc                   sn   z| j j| j| jdI dH  |  I dH  W dS  ty6 } ztd| j d| j dt| |d}~ww )zCancel the run.)r;   r9   Nz Failed to delete Kubernetes Job  in namespace : )r5   delete_namespaced_jobr;   r9   ro   r/   r   r:   rC   ra   rD   rD   rE   cancel   s   zKubernetesSubmittedRun.cancelc                   sH   t jds | jr"| jj| jjj| jjjdI d H  d | _d S d S d S )NWANDB_RELEASE_NAMErV   )	osenvirongetr=   r6   delete_namespaced_secretrP   r9   r;   rI   rD   rD   rE   ro      s   
z%KubernetesSubmittedRun._delete_secretc           
        s:  | j d u rd S t d| j  }zq| jdf| jdf| jdf| jdf| jdf| jdfg}|D ]Q\}}z.t|d| }t|d	| }|| j|d
I d H }|jD ]}||j	j
| jdI d H  qOW q- ttfy~ }	 ztd| d|	  W Y d }	~	q-d }	~	ww W d S  ty }	 ztd|	  W Y d }	~	d S d }	~	ww )N=servicejobpodr=   
deploymentnetwork_policylist_namespaced_delete_namespaced_)r;   rM   rV   zCould not clean up ru   z-Failed to clean up some auxiliary resources: )r?   r   r6   r5   r7   r8   getattrr;   rX   rP   r9   AttributeErrorr/   rY   rZ   r\   )
rC   rM   resource_cleanups
api_clientresource_typelist_methoddelete_method	resourcesresourcera   rD   rD   rE   $_delete_auxiliary_resources_by_label   sL   
	



"z;KubernetesSubmittedRun._delete_auxiliary_resources_by_label)r4   NN)r5   r*   r6   r+   r7   r)   r8   r-   r9   r:   r;   r<   r=   r>   r?   r<   r@   rA   r@   r:   r@   r<   r@   rc   r@   r   r@   rA   )__name__
__module____qualname____doc__rF   propertyrJ   rb   rr   rj   rx   ro   r   rD   rD   rD   rE   r3   [   s    	*




	r3   c                   @  sP   e Zd ZdZdddZedddZd ddZd!ddZd"ddZ	d#ddZ
dS )$CrdSubmittedRunz-Run submitted to a CRD backend, e.g. Volcano.groupr:   versionpluralr9   r;   r6   r+   
custom_apir,   r@   rA   c                 C  s4   || _ || _|| _|| _|| _|| _|| _d| _dS )a  Create a run object for tracking the progress of a CRD.

        Arguments:
            group: The API group of the CRD.
            version: The API version of the CRD.
            plural: The plural name of the CRD.
            name: The name of the CRD instance.
            namespace: The namespace of the CRD instance.
            core_api: The Kubernetes core API client.
            custom_api: The Kubernetes custom object API client.

        Raises:
            LaunchError: If the CRD instance does not exist.
        r   N)r   r   r   r9   r;   r6   r   rB   )rC   r   r   r   r9   r;   r6   r   rD   rD   rE   rF      s   
zCrdSubmittedRun.__init__c                 C  rG   )z"Get the name of the custom object.rH   rI   rD   rD   rE   rJ   !  rK   zCrdSubmittedRun.idr<   c              
     s   i }z-| j jd| j | jdI dH }dd |jD }|D ]}| j j|| jdI dH ||< qW n! tyQ } ztd| j dt	|  W Y d}~dS d}~ww |sVdS d	d | D }d

|S )zGet logs for custom object.zwandb/run-id=rL   Nc                 S  rN   rD   rO   rQ   rD   rD   rE   rT   .  rU   z,CrdSubmittedRun.get_logs.<locals>.<listcomp>rV   zFailed to get logs for ru   c                 S  s    g | ]\}}d | d| qS )zPod z:
rD   )rR   pod_namelogrD   rD   rE   rT   8  s     
)r6   rW   r9   r;   rX   r[   r/   rY   rZ   r:   join)rC   r`   r^   r_   r   ra   logs_as_arrayrD   rD   rE   rb   &  s*   
zCrdSubmittedRun.get_logsr   c                   s   t | jS )zGet status of custom object.)r   rj   r9   rI   rD   rD   rE   rj   ;  s   zCrdSubmittedRun.get_statusc                   sl   z| j j| j| j| j| j| jdI dH  W dS  ty5 } ztd| j d| j dt	| |d}~ww )zCancel the custom object.)r   r   r;   r   r9   NzFailed to delete CRD rt   ru   )
r   delete_namespaced_custom_objectr   r   r;   r   r9   r/   r   r:   rw   rD   rD   rE   rx   ?  s"   zCrdSubmittedRun.cancelrc   c                   sT   	 |   I dH }tt d| j d|  |jdv r!|jdkS tdI dH  q)z.Wait for this custom object to finish running.TNrd   re   rf   rg   r0   )rj   rY   rk   r   r9   rl   rm   rn   rp   rD   rD   rE   rr   N  s   

zCrdSubmittedRun.waitN)r   r:   r   r:   r   r:   r9   r:   r;   r:   r6   r+   r   r,   r@   rA   r   r   r   r   r   )r   r   r   r   rF   r   rJ   rb   rj   rx   rr   rD   rD   rD   rE   r      s    
!


r   c                      s   e Zd ZdZd< fddZd=ddZd>ddZ	d?d@d"d#ZdAd%d&ZdAd'd(Z	dAd)d*Z
dBd+d,Z	-	.		-dCdDd7d8ZdEd:d;Z  ZS )FKubernetesRunnerzLaunches runs onto kubernetes.apir   backend_configdict[str, Any]environmentr   registryr   r@   rA   c                   s   t  || || _|| _dS )a+  Create a Kubernetes runner.

        Arguments:
            api: The API client object.
            backend_config: The backend configuration.
            environment: The environment to launch runs into.

        Raises:
            LaunchError: If the Kubernetes configuration is invalid.
        N)superrF   r   r   )rC   r   r   r   r   	__class__rD   rE   rF   [  s   
zKubernetesRunner.__init__resource_argscontextr:   c                 C  sL   |r
|d  ddnd}| di  dp%| dp%| j di  dp%|S )zGet the namespace to launch into.

        Arguments:
            resource_args: The resource args to launch.
            context: The k8s config context.

        Returns:
            The namespace to launch into.
        r   r;   r4   rP   runner)r|   r   )rC   r   r   default_namespacerD   rD   rE   get_namespacep  s   zKubernetesRunner.get_namespacelaunch_projectr   	image_urir;   r6   r+   &tuple[dict[str, Any], V1Secret | None]c                   sJ  ddd}| | |di }ddd}| |di  |d	i }	d
di}
|
 |	di  |
di g}|di  |j|d t< d|d t< t rXt |d t	< |dslt
d|j d|j d|d< ||d< t|D ]%\}}d|vr|ddt| |d< d|vrdddgiddid|d< qt|jp| }|jr||d d< ntdd |D s|dusJ ||d d< t|| j|j|I dH }|durdd |j ig|
d!< t|||j|jdu || jt| jj }d}|D ]{}|d"pg }| D ]i\}}|d#krb|rbt s| jt rbtj d$}d%}|r,|d| 7 }n|d|j 7 }d&d' }t!t"t#j$d(d)t#j$d(d*t%d+t&|||||d,I dH }|'|d-|d.d/id0 q|'||d1 q||d"< q||
d< |
|	d< |	|d	< ||d< ||d< t(|td |j)rt*|| t rt(|t	t  ||fS )2a  Apply our default values, return job dict and api key secret.

        Arguments:
            resource_args (Dict[str, Any]): The resource args to launch.
            launch_project (LaunchProject): The launch project.
            builder (Optional[AbstractBuilder]): The builder.
            namespace (str): The namespace.
            core_api (CoreV1Api): The core api.

        Returns:
            Tuple[Dict[str, Any], Optional["V1Secret"]]: The resource args and api key secret.
        batch/v1Job)
apiVersionkindrP   r   <   )backoffLimitttlSecondsAfterFinishedspectemplaterestartPolicyNever
containerslabelstruer9   zlaunch--generateNamer;   launchsecurityContextFdropALLtypeRuntimeDefault)allowPrivilegeEscalationcapabilitiesseccompProfileimagec                 S  s   g | ]}d |v qS )r   rD   )rR   contrD   rD   rE   rT     rU   z5KubernetesRunner._inject_defaults.<locals>.<listcomp>Nregcred-imagePullSecretsenvWANDB_API_KEYry   zwandb-api-keyc                 S  s   t d|  d d S )N3Exception when ensuring Kubernetes API key secret: z. Retrying...)rY   rZ   )ra   rD   rD   rE   handle_exception  s   
z;KubernetesRunner._inject_defaults.<locals>.handle_exceptionr#   )seconds)minutes)initial_sleep	max_sleepmax_retries)backofffnon_excr6   secret_namer;   api_keysecretKeyRefpasswordr9   keyr9   	valueFromr9   value)+updater|   
setdefaultrun_idr   r   r   initializedr9   r   r"   target_entitytarget_project	enumerater:   override_entrypointget_job_entry_pointdocker_imageanymaybe_create_imagepull_secretr   inject_entrypoint_and_argsoverride_argsget_env_vars_dict_apir   r   r   rX   r   r   rz   r{   r   r   datetime	timedeltaAPI_KEY_SECRET_MAX_RETRIESensure_api_key_secretappendadd_label_to_podsjob_base_imageapply_code_mount_configuration)rC   r   r   r   r;   r6   r   job_metadatajob_specpod_templatepod_specr   ir   entry_pointr=   env_varsapi_key_secretr   r   r   release_namer   r   rD   rD   rE   _inject_defaults  s   









z!KubernetesRunner._inject_defaults,  r   #kubernetes_asyncio.client.ApiClientconfigtimeout_secondsintc           	   	     s  | d}| di  d}|r|stt d dS tt d| d| d t }|d	kr?| ||||I dH  n3|d
krO| ||||I dH  n#|dkr_| ||||I dH  ntt d| d t	
dI dH  t | }tt | d| d|dd dS )a1  Wait for a Kubernetes resource to be ready.

        Arguments:
            api_client: The Kubernetes API client.
            config: The resource configuration.
            namespace: The namespace where the resource was created.
            timeout_seconds: Maximum time to wait for readiness.
        r   rP   r9   z-Cannot wait for resource without kind or nameNzWaiting for z 'z' to be ready...
DeploymentServicePodz No specific readiness check for z, waiting 5 seconds...r0   z' is ready after z.1fs)r|   rY   r]   r   rk   time_wait_for_deployment_ready_wait_for_service_ready_wait_for_pod_readyrm   rn   )	rC   r   r  r;   r  resource_kindresource_name
start_timeelapsedrD   rD   rE   _wait_for_resource_ready1  s@   
z)KubernetesRunner._wait_for_resource_readyr9   c                   6   t j|  fdd}| ||I dH  dS )z"Wait for a Deployment to be ready.c                    s8    j dI d H } | j}|jr|jr|j|jkS dS )NrV   F)read_namespaced_deploymentrq   ready_replicasreplicas)r   rq   r7   r9   r;   rD   rE   check_deployment_readyp  s   zKKubernetesRunner._wait_for_deployment_ready.<locals>.check_deployment_readyN)r&   r(   r)   _wait_with_timeout)rC   r   r9   r;   r  r"  rD   r!  rE   r  f  s   z+KubernetesRunner._wait_for_deployment_readyc                   r  )z%Wait for a Service to have endpoints.c                    s8    j dI d H } | jr| jD ]}|jr dS qdS )NrV   TF)read_namespaced_endpointssubsets	addresses)	endpointssubsetr6   r9   r;   rD   rE   check_service_ready  s   
zEKubernetesRunner._wait_for_service_ready.<locals>.check_service_readyNr&   r(   r+   r#  )rC   r   r9   r;   r  r*  rD   r)  rE   r  }  s   
z(KubernetesRunner._wait_for_service_readyc                   r  )zWait for a Pod to be ready.c                    sH    j dI d H } | jjdkr"| jjr tdd | jjD S dS dS )NrV   Runningc                 s  s    | ]}|j V  qd S )N)ready)rR   rq   rD   rD   rE   	<genexpr>  s    zPKubernetesRunner._wait_for_pod_ready.<locals>.check_pod_ready.<locals>.<genexpr>TF)read_namespaced_podrq   phasecontainer_statusesall)r   r)  rD   rE   check_pod_ready  s   z=KubernetesRunner._wait_for_pod_ready.<locals>.check_pod_readyNr+  )rC   r   r9   r;   r  r3  rD   r)  rE   r    s   z$KubernetesRunner._wait_for_pod_readyc              
     s   t   }t   | |k rjz| I dH rW dS W nA tjjy@ } z|jdkr(ntt d| d|   W Y d}~nd}~w tyY } ztt d| d|   d}~ww t	
dI dH  t   | |k std| d| d)	z-Generic timeout wrapper for readiness checks.Ni  zError waiting for resource 'z': r   z
Resource 'z' not ready within z seconds)r  r&   r(   r/   rq   rY   r]   r   r\   rm   rn   r   )rC   
check_funcr  r9   r  ra   rD   rD   rE   r#    s4   
z#KubernetesRunner._wait_with_timeoutNTr   r  r>   wait_for_readyrc   wait_timeoutauxiliary_resource_label_valuer<   c
              
     sX  | di  |d  di  ||d d t< d|d d d< |	r)|	|d d t< || jt| jj }
d|
ddi}t	|| |	rIt
|t|	 |rkt|D ]}| dg }|dd	|jjd
did ||d< qOz#t| tjj|||dI dH  |r| ||||I dH  W dS W dS  ty } ztt d|  td| d}~ww )aZ  Prepare a service for launch.

        Arguments:
            api_client: The Kubernetes API client.
            config: The resource configuration to prepare.
            namespace: The namespace to create the resource in.
            run_id: The run ID to label the resource with.
            launch_project: The launch project to get environment variables from.
            api_key_secret: The API key secret to inject.
            wait_for_ready: Whether to wait for the resource to be ready after creation.
            wait_timeout: Maximum time in seconds to wait for resource readiness.
        rP   r   launch-agentwandb.ai/created-byWANDB_CONFIGz{}r   r   r   r   r   r   r;   Nz&Failed to create Kubernetes resource: )r   r   r   r   r   r   r   r   r|   add_wandb_envr   r   r   rP   r9   r   r&   utilscreate_from_dictr  r\   rY   r]   r   r   )rC   r   r  r;   r   r   r  r5  r6  r7  r  wandb_config_envr   r   ra   rD   rD   rE   _prepare_resource  s`   

z"KubernetesRunner._prepare_resourceAbstractRun | Nonec           $        s  t  I dH  |di }|stt d td|  t	t
|I dH \} jdurLtdu s:tdu r>td }tjt| |dd}|dvrijtjj }t|| |d	i |d	< |d	 d
i |d	 d
< d|d	 d
 t< t|td t rt|tt  t |d	 d
 t< jrt | i }j!rj!|d< j"rj"j#|d< t$|| t%& }	'|||(d^}
}}|d|
}
|d|}|d|}|)  d}t*|
||d}t j+|d z|	j,|
|||dI dH }W n+ t-y3 } zt./|j0}t12|}td| d|j3 d|j4 d| |d}~ww |d	i d}td| d|d	 d   t5||
||t%6 |	d}j7t8 rg|9 I dH  |S t
j%: }t
j%6 }t
j%; }t
j%< }'||=|||I dH \}j>j?j@j|jAd}|BtjC tDjEdg |}tFdj? d j> d j@ |rtt d!|  |d"d#|d$d%tGjH fd&d'|D  I dH  d(}d|v r|d|d  7 }t| zt
jIjJ |d)I dH }W nR t
jIjKyQ } z-|jLD ]#}t./|j0}|d*}|d+} td,j@ d-|  d|j4 d.| W Y d}~nd}~w tMyg } z
td/tN| dd}~ww |d0 }!|!jOj}"t + tP|||||"}#j7t8 r|#9 I dH  |#S )1a  Execute a launch project on Kubernetes.

        Arguments:
            launch_project: The launch project to execute.
            builder: The builder to use to build the image.

        Returns:
            The run object if the run was successful, otherwise None.
        N
kuberneteszyNote: no resource args specified. Add a Kubernetes yaml spec or other options in a json file with --resource-args <json>.z+Running Kubernetes job with resource args: a0  WANDB_LAUNCH_SOURCE_CODE_PVC_ environment variables not set. Unable to mount source code PVC into base image. Use the `codeMountPvcName` variable in the agent helm chart to enable base image jobs for this agent. See https://github.com/wandb/helm-charts/tree/main/charts/launch-agent for more information.r   r   )r   zbatch/v1beta1rP   r   r   argscommand/r   r   r   r  )r   r   r   )custom_resource)r   r   r;   r   bodyzError creating CRD of kind ru    r   r9   zCreated )r9   r   r   r;   r   r6   r   )project_nameentity_namer   run_namer   authoradditional_serviceszaux-r   zCreating additional services: r5  Tr6  r  c                   s<   g | ]}| d i r | d i j	qS )r  )r|   r@  r   )rR   r   r   r7  r   r;   r=   rC   r5  r6  rD   rE   rT     s     

z(KubernetesRunner.run.<locals>.<listcomp>zCreating Kubernetes jobr;  messagecodez(Failed to create Kubernetes job for run z (z): z3Unexpected exception when creating Kubernetes job: r   )Qr   ensure_initializedfill_macrosr|   rY   rk   r   _loggerinfor    r&   r   SOURCE_CODE_PVC_NAMESOURCE_CODE_PVC_MOUNT_PATHr   get_image_source_stringchange_project_dirrz   pathr   r   r   r   r   r   r<  r   r   r   r   r   r9   r   r   r   rD  add_entrypoint_args_overridesr(   r,   r   splitlowerr   monitor_namespacecreate_namespaced_custom_objectr/   jsonloadsrG  yamldumprq   reasonr   r+   r   r   rr   r*   r)   r-   r
  r   r   r   rL  r   r{   r   launch_specr!   rm   gatherr=  r>  FailToCreateErrorapi_exceptionsr\   r:   rP   r3   )$rC   r   r   r   r   code_subdirapi_versionr  	overridesr   r   r   _r   r   rF  responsera   rG  	body_yamlr9   submitted_runr5   r6   r7   r8   r   update_dictrM  msgexcresprP  job_responsejob_namesubmitted_jobrD   rN  rE   run  s^  






	








zKubernetesRunner.run)
r   r   r   r   r   r   r   r   r@   rA   )r   r   r   r   r@   r:   )r   r   r   r   r   r:   r;   r:   r6   r+   r@   r   )r  )
r   r  r  r   r;   r:   r  r  r@   rA   )
r   r  r9   r:   r;   r:   r  r  r@   rA   )r  r  r9   r:   r@   rA   )NTr  N)r   r  r  r   r;   r:   r   r:   r   r   r  r>   r5  rc   r6  r  r7  r<   r@   rA   )r   r   r   r:   r@   rA  )r   r   r   r   rF   r   r
  r  r  r  r  r#  r@  rv  __classcell__rD   rD   r   rE   r   X  s$    

 /
5


"Or   r   
list[dict]r  EntryPoint | Noner   	list[str]should_override_entrypointrc   r@   rA   c                 C  sJ   t t| D ]}|r|| | d< |r"| | dr|r"|j| | d< qdS )aP  Inject the entrypoint and args into the containers.

    Arguments:
        containers: The containers to inject the entrypoint and args into.
        entry_point: The entrypoint to inject.
        override_args: The args to inject.
        should_override_entrypoint: Whether to override the entrypoint.

    Returns:
        None
    rC  rD  N)rangelenr|   rD  )r   r  r   r{  r  rD   rD   rE   r     s   r   r6   r+   r   r:   r;   r   r.   c           	   
     s2  dt |  i}ddi}tj|tj|||dddd}zcz| ||I dH W W S  ty } zK|j	d	kr}| j
||d
I dH }|j|krt|jjddkrj| j||d
I dH  | ||I dH W  Y d}~W S td| d| |W  Y d}~W S  d}~ww  ty } z
tdt| dd}~ww )a<  Create a secret containing a user's wandb API key.

    Arguments:
        core_api: The Kubernetes CoreV1Api object.
        secret_name: The name to use for the secret.
        namespace: The namespace to create the secret in.
        api_key: The user's wandb API key

    Returns:
        The created secret
    r   r9  r8  )r9   r;   r   Secretzkubernetes.io/basic-authdatarP   r   r   N  rV   z.Kubernetes secret already exists in namespace z with incorrect data: r   r   )base64	b64encodeencodedecoder(   r.   V1ObjectMetacreate_namespaced_secretr/   rq   read_namespaced_secretr  rP   r   r|   r}   r   r\   r:   )	r6   r   r;   r   secret_datar   r=   ra   existing_secretrD   rD   rE   r     sT   	

r   r   r   r   r>   c           
   
     s&  d}t |ttfrdS | I dH \}}d|jt| d|   ddii}dtt	
|  i}tj|tjd| |dd	d
d}z2z| ||I dH W W S  ty| }	 z|	jdkrw| jd| |dI dH W  Y d}	~	W S  d}	~	ww  ty }	 z
tdt|	 dd}	~	ww )aI  Create a secret for pulling images from a private registry.

    Arguments:
        core_api: The Kubernetes CoreV1Api object.
        registry: The registry to pull from.
        run_id: The run id.
        namespace: The namespace to create the secret in.

    Returns:
        A secret if one was created, otherwise None.
    Nauths:zdeprecated@wandblaunch.com)authemailz.dockerconfigjsonr   rV   r~  zkubernetes.io/dockerconfigjsonr  r  z+Exception when creating Kubernetes secret: r   )
isinstancer
   r	   get_username_passwordurir  r  r  r  r_  dumpsr(   r.   r  r  r/   rq   r  r\   r   r:   )
r6   r   r   r;   r=   unametoken
creds_infor  ra   rD   rD   rE   r   M  sF   


r   rootdict | listr  dict[str, str]c                 C  sP   t | D ]!}|dg }|dd | D  ||d< d|v r%|d qdS )a  Injects wandb environment variables into specs.

    Recursively walks the spec and injects the environment variables into
    every container spec. Containers are identified by the "containers" key.

    This function treats the WANDB_RUN_ID and WANDB_GROUP_ID environment variables
    specially. If they are present in the spec, they will be overwritten. If a setting
    for WANDB_RUN_ID is provided in env_vars, then that environment variable will only be
    set in the first container modified by this function.

    Arguments:
        root: The spec to modify.
        env_vars: The environment variables to inject.

    Returns: None.
    r   c                 S  s   g | ]	\}}||d qS )r   rD   )rR   r   r   rD   rD   rE   rT     s    z!add_wandb_env.<locals>.<listcomp>WANDB_RUN_IDN)r   r   extendrX   pop)r  r  r   r   rD   rD   rE   r<    s   
r<  manifestr   Iterator[dict]c                 c  s~    t | tr| D ]	}t|E dH  qdS t | tr;d| v r&d| d v r&| V  |  D ]}t |ttfr:t|E dH  q*dS dS )zYield all pod specs in a manifest.

    Recursively traverses the manifest and yields all pod specs. Pod specs are
    identified by the presence of a "spec" key with a "containers" key in the
    value.
    Nr   r   )r  list
yield_podsdictvalues)r  itemr   rD   rD   rE   r    s   

r  	label_keylabel_valuec                 C  s2   t | D ]}|di }|di }|||< qdS )a  Add a label to all pod specs in a manifest.

    Recursively traverses the manifest and adds the label to all pod specs.
    Pod specs are identified by the presence of a "spec" key with a "containers"
    key in the value.

    Arguments:
        manifest: The manifest to modify.
        label_key: The label key to add.
        label_value: The label value to add.

    Returns: None.
    rP   r   N)r  r   )r  r  r  r   rP   r   rD   rD   rE   r     s
   
r   rj  r  c                 C  s   t | tr| D ]}t|| qdS t | trKd| v r?d| d v r?| d d }|D ]}d|v r4|d |d< d|v r>|d |d< q(|  D ]	}t|| qCdS dS )a  Add entrypoint and args overrides to all containers in a manifest.

    Recursively traverses the manifest and adds the entrypoint and args overrides
    to all containers. Containers are identified by the presence of a "spec" key
    with a "containers" key in the value.

    Arguments:
        manifest: The manifest to modify.
        overrides: Dictionary with args and entrypoint keys.

    Returns: None.
    r   r   rD  rC  N)r  r  rZ  r  r  )r  rj  r  r   	containerr   rD   rD   rE   rZ    s"   

rZ  projectr   c                 C  s   t dusJ | }t| D ]8}t|D ]}d|vrg |d< |d dt|d t|d< q|d }d|vr:g |d< |d ddt id	 qdS )
a  Apply code mount configuration to all containers in a manifest.

    Recursively traverses the manifest and adds the code mount configuration to
    all containers. Containers are identified by the presence of a "spec" key
    with a "containers" key in the value.

    Arguments:
        manifest: The manifest to modify.
        project: The launch project.

    Returns: None.
    NvolumeMountszwandb-source-code-volume)r9   	mountPathsubPath
workingDirr   volumes	claimName)r9   persistentVolumeClaim)rU  rW  r  r   r   r   )r  r  
source_dirr   r  r   rD   rD   rE   r     s.   
r   )
r   rx  r  ry  r   rz  r{  rc   r@   rA   )
r6   r+   r   r:   r;   r:   r   r:   r@   r.   )
r6   r+   r   r   r   r:   r;   r:   r@   r>   )r  r  r  r  r@   rA   )r  r   r@   r  )r  r  r  r:   r  r:   r@   rA   )r  r  rj  r  r@   rA   )r  r  r  r   r@   rA   )br   
__future__r   rm   r  r   r_  loggingrz   r  collections.abcr   typingr   ra  rY   wandb.apis.internalr   wandb.sdk.launch.agent.agentr   %wandb.sdk.launch.environment.abstractr   "wandb.sdk.launch.registry.abstractr   2wandb.sdk.launch.registry.azure_container_registryr	   (wandb.sdk.launch.registry.local_registryr
    wandb.sdk.launch.runner.abstractr   *wandb.sdk.launch.runner.kubernetes_monitorr   r   r   r   r   r   wandb.sdk.launch.utilsr   r   r   wandb.sdk.lib.retryr   r   
wandb.utilr   _project_specr   r   errorsr   r=  r   r   r   r   r    r!   r"   abstractr$   r%   r&   r(   )kubernetes_asyncio.client.api.apps_v1_apir)   *kubernetes_asyncio.client.api.batch_v1_apir*   )kubernetes_asyncio.client.api.core_v1_apir+   0kubernetes_asyncio.client.api.custom_objects_apir,   /kubernetes_asyncio.client.api.networking_v1_apir-   *kubernetes_asyncio.client.models.v1_secretr.   kubernetes_asyncio.client.restr/   TIMEOUTr   	getLoggerr   rS  r{   r|   rV  rU  r3   r   r   r   r   r   r<  r  r   rZ  r   rD   rD   rD   rE   <module>   s~     $	
 #[     
#

=
6


