
    d                        d Z ddlmZ ddlmZ ddlm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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 ddlmZ ddlZdZdZdZdZd Z G d dej@                        Z! G d de!      Z" G d de!      Z# G d de!      Z$ G d de!      Z% G d  d!e!      Z& G d" d#e!      Z' G d$ d%e!      Z(d& Z)d' Z*d;d(Z+d;d)Z,d;d*Z-d<d+Z.d, Z/	 	 	 d=d-Z0	 	 d>d.Z1d/ Z2d?d0Z3	 	 d>d1Z4d2 Z5d;d3Z6d;d4Z7	 	 	 d@d5Z8d6 Z9 G d7 d8 ejt                  ejv                  e<            Z= G d9 d: ejt                  ejv                  e=            Z>y)Az.Library for defining Binary backed operations.    )absolute_import)division)unicode_literalsN)structured_messages)config)
exceptions)execution_utils)log)yaml)
console_io)local_state)update_manager)files)	platformszdError executing command [{command}] (with context [{context}]). Process exited with code {exit_code}zExecutable [{}] not found.z3Expected structured message, logging as raw text:{}zThis command requires the `{binary}` component to be installed. Would you like to install the `{binary}` component to continue command execution?c                     t        j                  t        j                  | j                  | j
                  | j                               y )N)commandcontext	exit_code)r
   error_DEFAULT_FAILURE_ERROR_MESSAGEformatexecuted_commandr   r   )result_objects    ?lib/googlecloudsdk/command_lib/util/anthos/binary_operations.py_LogDefaultOperationFailurer   6   s<    ))$++00''!++ , -.    c                       e Zd ZdZy)BinaryOperationErrorz'Base class for binary operation errors.N__name__
__module____qualname____doc__ r   r   r   r   >   s    /r   r   c                   "     e Zd ZdZ fdZ xZS )BinaryExecutionError5Raised if there is an error executing the executable.c                 L    t         t        |   dj                  ||             y )Nz$Error executing binary on [{}]: [{}])superr&   __init__r   )selforiginal_errorr   	__class__s      r   r*   zBinaryExecutionError.__init__E   s)    	

?FF~' (r   r    r!   r"   r#   r*   __classcell__r-   s   @r   r&   r&   B   s    =( (r   r&   c                       e Zd ZdZy)InvalidOperationForBinaryz8Raised when an invalid Operation is invoked on a binary.Nr   r$   r   r   r2   r2   K   s    @r   r2   c                       e Zd ZdZy)StructuredOutputErrorz@Raised when there is a problem processing as sturctured message.Nr   r$   r   r   r4   r4   O   s    Hr   r4   c                   $     e Zd ZdZd fd	Z xZS )MissingExecutableExceptionz5Raised if an executable can not be found on the path.c                 `    |r|}nt         j                  |      }t        t        |   |       y N)_DEFAULT_MISSING_EXEC_MESSAGEr   r)   r6   r*   )r+   	exec_namecustom_message	error_msgr-   s       r   r*   z#MissingExecutableException.__init__V   s+     i/66yAi	
$d4Y?r   r8   r.   r0   s   @r   r6   r6   S   s    =@ @r   r6   c                   "     e Zd ZdZ fdZ xZS )ExecutionErrorr'   c                 L    t         t        |   dj                  ||             y )Nz%Error executing command on [{}]: [{}])r)   r>   r*   r   )r+   r   r   r-   s      r   r*   zExecutionError.__init__c   s(    	.
@GGu r   r.   r0   s   @r   r>   r>   `   s    = r   r>   c                   "     e Zd ZdZ fdZ xZS )InvalidWorkingDirectoryErrorzCRaised when an invalid path is passed for binary working directory.c                 L    t         t        |   dj                  ||             y )Nz2Error executing command on [{}]. Invalid Path [{}])r)   rA   r*   r   )r+   r   pathr-   s      r   r*   z%InvalidWorkingDirectoryError.__init__l   s&    	
&6<CCT	r   r.   r0   s   @r   rA   rA   i   s    K r   rA   c                       e Zd ZdZy)ArgumentErrorz:Raised if there is an error parsing argument to a command.Nr   r$   r   r   rE   rE   r   s    Br   rE   c                       fd}|S )z.Default processing for stdout from subprocess.c                 :    | j                         } | r| _        y y r8   )rstripstdout)rI   result_holders    r   HandleStdOutz*DefaultStdOutHandler.<locals>.HandleStdOuty       ]]_F#m r   r$   )rJ   rK   s   ` r   DefaultStdOutHandlerrM   v       $
 
r   c                       fd}|S )z.Default processing for stderr from subprocess.c                 :    | j                         } | r| _        y y r8   )rH   stderr)rQ   rJ   s    r   HandleStdErrz*DefaultStdErrHandler.<locals>.HandleStdErr   rL   r   r$   )rJ   rR   s   ` r   DefaultStdErrHandlerrS      rN   r   c                 f    | j                   dk7  rd| _        |r| j                  rt        |        yyy)z1Default processing for subprocess failure status.r   TN)r   failedr   rJ   show_exec_errors     r   DefaultFailureHandlerrX      s2    !M--. ._r   c                       fd}|S )z8Default processing for streaming stdout from subprocess.c                     | r%| j                          t        j                  |        r/j                  sg _        j                  j	                  |        y y r8   )rH   r
   PrintrI   appendlinecapture_outputrJ   s    r   rK   z-DefaultStreamOutHandler.<locals>.HandleStdOut   sG    
kkm	iio!!!!!$' r   r$   )rJ   r_   rK   s   `` r   DefaultStreamOutHandlerr`      s    ( 
r   c                       fd}|S )z8Default processing for streaming stderr from subprocess.c                     | rt         j                  j                  |        r/j                  sg _        j                  j	                  |        y y r8   )r
   statusr[   rQ   r\   r]   s    r   rR   z-DefaultStreamErrHandler.<locals>.HandleStdErr   sE    	jjt!!!!!$' r   r$   )rJ   r_   rR   s   `` r   DefaultStreamErrHandlerrd      s    ( 
r   c                     	 t         j                  j                  | j                         |      S # t         j                  t         j
                  f$ r!}t        dj                  | |            d}~ww xY w)a  Process a line of structured output into an OutputMessgage.

  Args:
    msg_string: string, line JSON/YAML formatted raw output text.
    as_json: boolean, if True set default string representation for parsed
      message to JSON. If False (default) use YAML.

  Returns:
    OutputMessage, parsed Message

  Raises: StructuredOutputError is msg_string can not be parsed as an
    OutputMessage.

  )as_jsonz=Error processing message [{msg}] as an OutputMessage: {error})msgr   N)smOutputMessage
FromStringstripMessageParsingErrorInvalidMessageErrorr4   r   )
msg_stringrf   es      r   ReadStructuredOutputrp      sr    K&&z'7'7'97&KK

 
 ""8"8	9 K
 !**0&Zq&*IK KKs   .1 #A5A00A5c                 H   d}d}| r| j                         }t        |      }|j                  rIt        j                  j                  |j                         t        j
                  |j                         nt        j
                  |j                         |j                  |fS )a  Parse and log stdout text as an OutputMessage.

  Attempts to parse line into an OutputMessage and log any resource output or
  status messages accordingly. If message can not be parsed, raises a
  StructuredOutputError.

  Args:
    line: string, line of output read from stdout.

  Returns:
    Tuple: (str, object): Tuple of parsed OutputMessage body and
       processed resources or None.

  Raises: StructuredOutputError, if line can not be parsed.
  N)rk   rp   resource_bodyr
   rc   r[   body)r^   rg   	resourcesmsg_recs       r   _LogStructuredStdOutrv      sx      	#)	jjlG
w
'C 	jjsxx 	ii!!"	ii
((I	r   c                     | j                   sg | _         |r| j                   j                  |       |r| j                   j                  |       |r| j                   j                  |       yy)z8Update OperationResult from OutputMessage or plain text.N)rI   r\   )rJ   output_messageresource_output
raw_outputs       r   _CaptureStdOutr{      s_    
 
		M/0
+ r   c                       fd}|S )zBDefault processing for structured stdout from threaded subprocess.c                 D   | r1| j                         }	 t        |      \  }}rt        ||       yyy# t        $ r`}r(t	        j
                  t        j                  |             t        j                  j                  |       t        |       Y d}~yd}~ww xY w)zProcess structured stdout.)rx   ry   rz   N)
rk   rv   r{   r4   r
   warning_STRUCTURED_TEXT_EXPECTED_ERRORr   outr[   )r^   ru   rg   rt   smer_   rJ   warn_if_not_stuctureds        r   rK   z7DefaultStreamStructuredOutHandler.<locals>.HandleStdOut   s    

g	:-g6Y
CL 	  # : 
++5<<SA
Bg}99	:s   6 	BABBr$   )rJ   r_   r   rK   s   ``` r   !DefaultStreamStructuredOutHandlerr      s    
: 
r   c                 ~   | j                   rt        j                  | j                         r| j                   n(| j                   j                         j	                  d      }g }g }|D ]P  }t        |      }|j                  |j                         |j                  s6|j                  |j                         R ||fS y)a  Default processing for structured stdout from a non-threaded subprocess.

  Attempts to parse result_holder.stdstdout into an OutputMessage and return
  a tuple of output messages and resource content.

  Args:
    result_holder:  OperationResult

  Returns:
    ([str], [JSON]), Tuple of output messages and resource content.
  Raises:
    StructuredOutputError if result_holder can not be processed.
  
NN)	rI   r   	list_likerk   splitrp   r\   rs   rr   )rJ   all_msgmsgsrt   ru   rg   s         r   ProcessStructuredOutr     s      $}/C/C D""$**40  DI )c
kk#((			**+	  ?	r   c                 V   | j                   sg | _         |rv|j                  r%| j                   j                  |j                         |j                         r4| j                   j                  |j                  j                                yy|r| j                   j                  |       yy)z?Update OperationResult either from OutputMessage or plain text.N)rQ   rs   r\   IsErrorerror_detailsFormat)rJ   rx   rz   s      r   _CaptureStdErrr   .  s    			M!!."5"56!!.">">"E"E"GH  
+ r   c                       fd}|S )zBDefault processing for structured stderr from threaded subprocess.c                    | rZ| j                         }	 t        |       }|j                         r|j                  dk(  r.t	        j
                  |j                  j                                n|j                  dk(  r.t	        j                  |j                  j                                n|j                  dk(  r.t	        j                  |j                  j                                nf|j                  dk(  rWt	        j                  |j                  j                                n)t        j                  j                  |j                         rt        |       yyy# t        $ rg}r(t	        j                  t         j#                  |             t        j                  j                  |       rt        |       Y d}~yY d}~yd}~ww xY w)ak  Handle line as a structured message.

    Attempts to parse line into an OutputMessage and log any errors or warnings
    accordingly. If line cannot be parsed as an OutputMessage, logs it as plain
    text to stderr. If capture_output is True will capture any logged text to
    result_holder.

    Args:
      line: string, line of output read from stderr.
    infor   r   debug)rx   r~   N)rk   rp   r   levelr
   r   r   r   r   r   r   rc   r[   rs   r   r4   r   r   )r^   ru   rg   r   r_   rJ   r   s       r   rR   z7DefaultStreamStructuredErrHandler.<locals>.HandleStdErr@  sH    

g<"4(;;=YY& HHS&&--/0yyG#IIc''..01yyI%KK))0023yyG#IIc''..01
**

388
$
s
;  " # < 
++5<<SA
B

!
7
;
; 	<s   EE   	G)AGGr$   )rJ   r_   r   rR   s   ``` r   !DefaultStreamStructuredErrHandlerr   ;  s    
!<F 
r   c                    | j                   rt        j                  | j                         r| j                   n(| j                   j                         j	                  d      }g }g }|D ]b  }t        |      }|j                         r*|j                  |j                  j                                H|j                  |j                         d ||fS y)a  Default processing for structured stderr from non-threaded subprocess.

  Attempts to parse result_holder.stderr into an OutputMessage and return any
  status messages or raised errors.

  Args:
    result_holder:  OperationResult

  Returns:
    ([status messages], [errors]), Tuple of status messages and errors.
  Raises:
    StructuredOutputError if result_holder can not be processed.
  r   r   )rQ   r   r   rk   r   rp   r   r\   r   r   rs   )rJ   r   messageserrorsru   rg   s         r   ProcessStructuredErrr   f  s      $}/C/C D""$**40  HF )c	c''..01!  V	r   c                 ~    | j                   dk7  r| j                  sd| _        |r| j                  rt        |        yyy)a  Processing for subprocess where non-zero exit status is not always failure.

  Uses rule of thumb that defines success as:
  - a process with zero exit status OR
  - a process with non-zero exit status AND some stdout output.

  All others are considered failed.

  Args:
    result_holder: OperationResult, result of command execution
    show_exec_error: bool, if true log the process command and exit status the
      terminal for failed executions.

  Returns:
    None. Sets the failed attribute of the result_holder.
  r   TN)r   rI   rU   r   rV   s     r   NonZeroSuccessFailureHandlerr     s<    " !-*>*>M--. ._r   c                 2   t        j                         j                  rt        j                  j                         nd }	 t        j                  |d      }| |j                  |      v S # t        j                  $ r t        j                  d       Y y w xY w)NF)platform_filterwarn)include_hiddenz:Component check failed. Could not verify SDK install path.)r   Pathssdk_rootr   PlatformCurrentr   UpdateManagerGetCurrentVersionsInformationr   Errorr
   r   )component_namecheck_hiddenplatformmanagers       r   CheckBinaryComponentInstalledr     s    -3\\^-D-DY'')$(**8%PGWBB# C % % %			 KKLMs    *A+ +(BBc                 |   t        | |      }|r<t        j                  j                  t	        j
                         j                  |       S t        j                  |       }|rt        j                  d|       |S |r6t        j                  d|        t        | t        j                  |             S t        | |      )a  Check if binary is installed and return path or raise error.

  Prefer the installed component over any version found on path.

  Args:
    binary_name: str, name of binary to search for.
    check_hidden: bool, whether to check hidden components for the binary.
    custom_message: str, custom message to used by MissingExecutableException if
      thrown.
    install_if_missing: bool, if true will prompt user to install binary if not
      found.

  Returns:
    Path to executable if found on path or installed component.

  Raises:
    MissingExecutableException: if executable can not be found or can not be
     installed as a component.
  zFound executable on path: %szInstalling %s...)binary)r   osrC   joinr   r   sdk_bin_pathr   FindExecutableOnPathr
   r   InstallBinaryNoOverrides_INSTALL_MISSING_EXEC_PROMPTr   r6   )binary_namer   r;   install_if_missingis_componentpath_executables         r   CheckForInstalledBinaryr     s    . /{LI,77<<33[AA..{;/II,o>II +.#1888LN N 	#;??r   c                 F   t        j                  d|ddj                  |              t        j                  j                         }t        j                  |      }|j                  | g       t        j                  |       }|r|S t        | dj                  |             )zFHelper method for installing binary dependencies within command execs.zPausing command execution:Tz8Aborting component install for {} and command execution.)messageprompt_stringcancel_on_nocancel_string)r   z{} binary not installed)r   PromptContinuer   r   r   r   r   r   Installr   r   r6   )r   promptr   update_manager_clientr   s        r   r   r     s    *Nvk '')((66xP...{;/",33K@	B Br   c                       e Zd ZdZ G d de      Z	 	 	 	 	 	 	 	 ddZed        Zed        Z	ed        Z
dd	Zej                  d
        Zd Zy)BinaryBackedOperationzBClass for declarative operations implemented as external binaries.c                   4    e Zd ZdZ	 	 	 	 	 ddZd Zd Zd Zy)%BinaryBackedOperation.OperationResultz6Generic Holder for Operation return values and errors.Nc                 X    || _         || _        || _        || _        || _        || _        y r8   )r   rI   rQ   r   r   rU   )r+   command_stroutputr   rc   rU   execution_contexts          r   r*   z.BinaryBackedOperation.OperationResult.__init__  s/     *ddkdkdn&dldkr   c                    t        j                         }| j                  |d<   | j                  |d<   | j                  |d<   | j
                  |d<   | j                  |d<   | j                  |d<   t        j                  |      S )Nr   rI   rQ   r   rU   r   )
collectionsOrderedDictr   rI   rQ   r   rU   r   r   dump)r+   r   s     r   __str__z-BinaryBackedOperation.OperationResult.__str__  sw    &&(f#'#8#8f fXfX NNf[fX$(LLf !YYvr   c                 x   t        |t        j                        r| j                  |j                  k(  xr | j                  |j                  k(  xrj | j
                  |j
                  k(  xrO | j                  |j                  k(  xr4 | j                  |j                  k(  xr | j                  |j                  k(  S y)NF)	
isinstancer   OperationResultr   rI   rQ   r   rU   r   )r+   others     r   __eq__z,BinaryBackedOperation.OperationResult.__eq__  s    	E0@@	A%%)?)?? Nu||+N04u||0KN%//1N u||+N 150M	O r   c                 "    | j                         S r8   )r   r+   s    r   __repr__z.BinaryBackedOperation.OperationResult.__repr__  s    \\^r   )NNr   FN)r    r!   r"   r#   r*   r   r   r   r$   r   r   r   r     s*    @ #'r   r   Nc
                     t        |||	|r|d   nd      | _        || _        || _        || _        |xs t
        | _        |xs t        | _        |xs t        | _
        y)a  Creates the Binary Operation.

    Args:
      binary: executable, the name of binary containing the underlying
        operations that this class will invoke.
      binary_version: string, version of the wrapped binary.
      check_hidden: bool, whether to look for the binary in hidden components.
      std_out_func: callable(OperationResult, **kwargs), returns a function to
        call to process stdout from executable and build OperationResult
      std_err_func: callable(OperationResult, **kwargs), returns a function to
        call to process stderr from executable and build OperationResult
      failure_func: callable(OperationResult), function to call to determine if
        the operation result is a failure. Useful for cases where underlying
        binary can exit with non-zero error code yet still succeed.
      default_args: dict{str:str}, mapping of parameter names to values
        containing default/static values that should always be passed to the
        command.
      custom_errors: dict(str:str}, map of custom exception messages to be used
        for known errors.
      install_if_missing: bool, if True prompt for install on missing component.
    MISSING_EXECN)r   r   r   r;   )r   _executable_binary_version_default_argsrM   std_out_handlerrS   std_err_handlerrX   set_failure_status)
r+   r   binary_versionr   std_out_funcstd_err_funcfailure_funcdefault_argscustom_errorsr   s
             r   r*   zBinaryBackedOperation.__init__  si    > /!-8E}^44	QD
 DL"DM%D'?+?D'?+?D*C.CDr   c                     | j                   S r8   )r   r   s    r   r   z!BinaryBackedOperation.binary_name9  s    <<r   c                     | j                   S r8   )r   r   s    r   
executablez BinaryBackedOperation.executable=  s    r   c                     | j                   S r8   )r   r   s    r   defaultszBinaryBackedOperation.defaultsA  s    r   c           	      T   |||j                  d      d}| j                  ||      }| j                  |      }| j                  |      }t        j
                  j                  |d         }		 |j                  d      }
|
r+t        j
                  j                  |
      st        |	|
      t        j                  |d||||
|      }||_        | j                  ||j                  dd	             |S # t        j                  t        j                  f$ r}t        |	|      d}~ww xY w)
  Execute binary and return operation result.

     Will parse args from kwargs into a list of args to pass to underlying
     binary and then attempt to execute it. Will use configured stdout, stderr
     and failure handlers for this operation if configured or module defaults.

    Args:
      cmd: [str], command to be executed with args
      stdin: str, data to send to binary on stdin
      env: {str, str}, environment vars to send to binary.
      **kwargs: mapping of additional arguments to pass to the underlying
        executor.

    Returns:
      OperationResult: execution result for this invocation of the binary.

    Raises:
      ArgumentError, if there is an error parsing the supplied arguments.
      BinaryOperationError, if there is an error executing the binary.
    execution_direnvstdinexec_dirr   r   r   Targsno_exitout_funcerr_funcin_strcwdr   NrW   F)getr   r   r   r   rC   basenameisdirrA   r	   ExecPermissionErrorInvalidCommandErrorr>   r   r   r+   cmdr   r   kwargs
op_contextrJ   r   r   short_cmd_nameworking_dirr   ro   s                r   _ExecutezBinaryBackedOperation._ExecuteE  s)   , JJ/J
 ((: ) 7M **=9O**=9OWW%%c!f-N.JJ/k	RWW]];7*>;GG!&&""i (MM6::6G+OP ++//1 .>1--.s   .AC3 3#D'D""D'c                      y)af  Parse and validate kwargs into command argument list.

    Will process any default_args first before processing kwargs, overriding as
    needed. Will also perform any validation on passed arguments. If calling a
    named sub-command on the underlying binary (vs. just executing the root
    binary), the sub-command should be the 1st argument returned in the list.

    Args:
      **kwargs: keyword arguments for the underlying command.

    Returns:
     list of arguments to pass to execution of underlying command.

    Raises:
      ArgumentError: if there is an error parsing or validating arguments.
    Nr$   )r+   r  s     r   _ParseArgsForCommandz*BinaryBackedOperation._ParseArgsForCommandz  s    $ 	r   c                     | j                   g}|j                   | j                  di |        | j                  |fi |S )Nr$   )r   extendr
  r  )r+   r  r  s      r   __call__zBinaryBackedOperation.__call__  sA    ??
CJJ(t((26234=='''r   )NFNNNNNFr   )r    r!   r"   r#   objectr   r*   propertyr   r   r   r  abcabstractmethodr
  r  r$   r   r   r   r     s    J$ $P #!    !"')DV      3j 	 	&(r   r   c                   @     e Zd ZdZ	 	 	 	 	 	 	 	 	 	 d fd	ZddZ xZS )StreamingBinaryBackedOperationzEExtend Binary Operations for binaries which require streaming output.c                     t         t        |   |||||||||	       |	| _        |
rt        }t
        }nt        }t        }|xs || _        |xs || _	        |
| _
        y r8   )r)   r  r*   r_   r   r   r`   rd   r   r   structured_output)r+   r   r   r   r   r   r   r   r   r_   r  r   default_out_handlerdefault_err_handlerr-   s                 r   r*   z'StreamingBinaryBackedOperation.__init__  sw     

(
|%|\&(:< )D==33'>+>D'>+>D.Dr   c           	         |||j                  d      d}| j                  ||      }| j                  || j                        }| j	                  || j                        }t
        j                  j                  |d         }		 |j                  d      }
|
r+t
        j                  j                  |
      st        |	|
      t        j                  |d||||
|      }||_        | j!                  ||j                  d	d
             |S # t        j                  t        j                  f$ r}t        |	|      d}~ww xY w)r   r   r   r   )rJ   r_   r   Tr   NrW   F)r   r   r   r_   r   r   rC   r   r   rA   r	   ExecWithStreamingOutputr   r  r>   r   r   r  s                r   r  z'StreamingBinaryBackedOperation._Execute  sK   , JJ/J
 ((: ) 7M **#D4G4G + IO**#D4G4G + IOWW%%c!f-N.JJ/k	RWW]];7*>;GG!99""i (MM6::6G+OP ++//1 .>1--.s   AD #D?.D::D?)
NFNNNNNFFFr   )r    r!   r"   r#   r*   r  r/   r0   s   @r   r  r    s0    M #!    !#!&"'/64r   r  )F)T)NNN)FTr   )FNF)?r#   
__future__r   r   r   r  r   r   &googlecloudsdk.command_lib.util.anthosr   rh   googlecloudsdk.corer   r   core_exceptionsr	   r
   r   googlecloudsdk.core.consoler   googlecloudsdk.core.updaterr   r   googlecloudsdk.core.utilr   r   sixr   r9   r   r   r   r   r   r&   r2   r4   r6   r>   rA   rE   rM   rS   rX   r`   rd   rp   rv   r{   r   r   r   r   r   r   r   r   r   with_metaclassABCMetar  r   r  r$   r   r   <module>r$     s   5 &  ' 
  	 L & = / # $ 2 3 6 * . 
+  != $<  .0?00 0(/ (A 4 AI0 I
@!5 
@) #7 C( C/K.D #'#'"," 6;<@.<
, 6;<@(V@/. */+//4&@RB(l(.C..s{{FC l(^SCs{{$9:Sr   