3
 a                 @   sl  d Z ddl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ZyddlmZ W n ek
r|   Y nX 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ZdZdZdZ dZ!dZ"dddgZ#da$G dd dej%Z&d~ddZ'dd Z(dddZ)d d! Z*d"d# Z+d$d% Z,d&d' Z-d(d) Z.d*d+ Z/d,d- Z0d.d/ Z1d0d1 Z2d2d3 Z3d4d5 Z4d6d7 Z5d8d9 Z6d:d; Z7d<d= Z8d>d? Z9d@dAdBdCZ:dDdE Z;dFdG Z<e(dHdI Z=e(dJdK Z>e(e)ej?e'dLdMdN Z@e(e)ej?e'dOdPdQ ZAe(e) e'dReBdSdTdUZCejDeEeBdVdWdXZFejDeGeEeBdYdZd[ZHejDeGd\d]d^ZIe(e'd_d`da ZJe*e(e'dbdcdd ZKdedf ZLdgdh ZMddidjZNddkdlZOejDdmdndoZPe) ejDdmdpdqZQe(e'drejDdmdsdtZRdudv ZSddwdxZTdydz ZUeUdd{d|ZVeWd}krhe	jXeV  dS )z8Client to manage Ubuntu Advantage services on a machine.    N)wraps)List)config)contract)entitlements)
exceptions)security)status)util)version)identity)CONFIG_FIELD_ENVVAR_ALLOWLISTZuaz{name} {command} [flags]zAUse {name} {command} --help for more information about a command.z}Account: {account}
Subscription: {subscription}
Valid until: {contract_expiry}
Technical support level: {tech_support_level}
z$https://auth.contracts.canonical.comzD%(asctime)s - %(filename)s:(%(lineno)d) [%(levelname)s]: %(message)sZtabularjsonyamlc                   sN   e Zd Zdddejdddfeddd fddZdd Zd fd	d
	Z  Z	S )UAArgumentParserNz	List[str])	base_descnon_beta_services_descbeta_services_descc                s*   t  j||||d || _|| _|| _d S )N)progusageepilogformatter_class)super__init__r   r   r   )selfr   r   r   r   r   r   r   )	__class__ ./usr/lib/python3/dist-packages/uaclient/cli.pyr   ?   s    
zUAArgumentParser.__init__c             C   s    | j tj | jd|d  d S )N   
)print_usagesysstderrexit)r   messager   r   r   errorT   s    zUAArgumentParser.errorFc                sZ   | j | j| jg}t|rHt| j}|r4t|| j }dj| j g| | _t j|d d S )Nr   )file)	r   r   r   anysortedjoindescriptionr   
print_help)r   r&   show_allZ	desc_varsZservices)r   r   r   r+   X   s    
zUAArgumentParser.print_help)NF)
__name__
__module____qualname__argparseZHelpFormatterstrr   r%   r+   __classcell__r   r   )r   r   r   >   s   r   c                s    fdd}|S )a  Decorator asserting exclusive access to lock file

    Create a lock file if absent. The lock file will contain a pid of the
        running process, and a customer-visible description of the lock holder.

    :param lock_holder: String with the service name or command which is
        holding the lock.

        This lock_holder string will be customer visible in status.json.

    :raises: LockHeldError if lock is held.
    c                s   t   fdd}|S )Nc                sx   |j  \}}|dkr$tj||d|jddjtj  dj}|jd| |ja	 | |f|}|jd d a	|S )Nr   )Zlock_requestlock_holderpidlockz{}:{}zOperation in progress: {} )
Zcheck_lock_infor   LockHeldErrorwrite_cacheformatosgetpidZ
add_noticeZdelete_cache_key_CLEAR_LOCK_FILE)argscfgkwargsZlock_pidZcur_lock_holderZ
notice_msgZretval)fr3   r   r   new_fu   s    

z0assert_lock_file.<locals>.wrapper.<locals>.new_f)r   )r@   rA   )r3   )r@   r   wrappert   s    z!assert_lock_file.<locals>.wrapperr   )r3   rB   r   )r3   r   assert_lock_filef   s    rC   c                s   t   fdd}|S )zDecorator asserting root userc                 s   t j dkrtj  | |S )Nr   )r:   getuidr   ZNonRootUserError)r=   r?   )r@   r   r   rA      s    zassert_root.<locals>.new_f)r   )r@   rA   r   )r@   r   assert_root   s    rE   c                s    fdd}|S )zDecorator asserting attached config.

    :param unattached_msg_tmpl: Optional msg template to format if raising an
        UnattachedError
    c                s   t   fdd}|S )Nc                sN   |j s@r4t| dd}jdj|d}tj|}ntj }| | |f|S )NserviceNonez, )name)is_attachedgetattrr9   r)   r   ZUnattachedError)r=   r>   r?   namesmsg	exception)r@   unattached_msg_tmplr   r   rA      s    z/assert_attached.<locals>.wrapper.<locals>.new_f)r   )r@   rA   )rN   )r@   r   rB      s    z assert_attached.<locals>.wrapperr   )rN   rB   r   )rN   r   assert_attached   s    rO   c                s   t   fdd}|S )z&Decorator asserting unattached config.c                s   |j rtj| | |S )N)rI   r   AlreadyAttachedError)r=   r>   )r@   r   r   rA      s    
z"assert_not_attached.<locals>.new_f)r   )r@   rA   r   )r@   r   assert_not_attached   s    rQ   c             C   s*   d| _ d| _tjt| j d| _d| j_| S )z9Build or extend an arg parser for auto-attach subcommand.zauto-attachzDAutomatically attach an Ubuntu Advantage token on Ubuntu Pro images.)rH   commandFlags)r   r*   
USAGE_TMPLr9   NAMEr   
_optionalstitle)parserr   r   r   auto_attach_parser   s
    rY   c             C   s0   t jtdd| _d| _d| _| jdddd | S )	z;Build or extend an arg parser for 'config show' subcommand.z
show [key])rH   rR   showz(Show customisable configuration settingskey?z6Optional key or key(s) to show configuration settings.)nargshelp)rT   r9   rU   r   r   r*   add_argument)rX   r   r   r   config_show_parser   s    r`   c             C   sD   t jtdd| _d| _d| _d| j_| jddjdj	t
jd	 | S )
z:Build or extend an arg parser for 'config set' subcommand.zset <key>=<value>)rH   rR   setz5Set and apply Ubuntu Advantage configuration settingsrS   key_value_pairzQkey=value pair to configure for Ubuntu Advantage services. Key must be one of: {}z, )r^   )rT   r9   rU   r   r   r*   rV   rW   r_   r)   r   UA_CONFIGURABLE_KEYS)rX   r   r   r   config_set_parser   s    rd   c             C   sF   t jtdd| _d| _d| _| jddjdjtj	dd d	| j
_| S )
z<Build or extend an arg parser for 'config unset' subcommand.zunset <key>)rH   rR   unsetz,Unset Ubuntu Advantage configuration settingr[   zEconfiguration key to unset from Ubuntu Advantage services. One of: {}z, )r^   metavarrS   )rT   r9   rU   r   r   r*   r_   r)   r   rc   rV   rW   )rX   r   r   r   config_unset_parser   s    rg   c             C   s   t jtdd| _d| _d| _d| j_| jdddd	}|j	d
dd}|j
td t| |j	ddd}|j
td t| |j	ddd}|j
td t| | S )z4Build or extend an arg parser for config subcommand.zconfig <command>)rH   rR   r   z%Manage Ubuntu Advantage configurationrS   zAvailable CommandsrR   r6   )rW   destrf   rZ   z2show all Ubuntu Advantage configuration setting(s))r^   )actionra   z*set Ubuntu Advantage configuration settingre   z,unset Ubuntu Advantage configuration setting)rT   r9   rU   r   r   r*   rV   rW   add_subparsers
add_parserset_defaultsaction_config_showr`   action_config_setrd   action_config_unsetrg   )rX   
subparsersZparser_showZ
parser_setZparser_unsetr   r   r   config_parser   s&    


rq   c             C   sP   t jtdd| _d| _d| _d| j_| jdddjt	d	 | jd
dddd | S )z4Build or extend an arg parser for attach subcommand.zattach <token>)rH   rR   attachz_Attach this machine to Ubuntu Advantage with a token obtained from https://ubuntu.com/advantagerS   tokenr\   z6token obtained for Ubuntu Advantage authentication: {})r]   r^   z--no-auto-enableZstore_falseauto_enablez4do not enable any recommended services automatically)ri   rh   r^   )
rT   r9   rU   r   r   r*   rV   rW   r_   UA_AUTH_TOKEN_URL)rX   r   r   r   attach_parser  s    
rv   c             C   s6   t jtdd| _d| _d| _d| j_| jddd | S )	z1Build or extend an arg parser for fix subcommand.z"fix <CVE-yyyy-nnnn+>|<USN-nnnn-d+>)rH   rR   fixzLInspect and resolve CVEs and USNs (Ubuntu Security Notices) on this machine.rS   security_issuezwSecurity vulnerability ID to inspect and resolve on this system. Format: CVE-yyyy-nnnn, CVE-yyyy-nnnnnnn or USN-nnnn-dd)r^   )	rT   r9   rU   r   r   r*   rV   rW   r_   )rX   r   r   r   
fix_parser2  s    ry   c             C   s@   d| _ d| _tjtdd| _d| j_| jdddgd	d
dd | S )z5Build or extend an arg parser for refresh subcommand.refreshz?Refresh existing Ubuntu Advantage contract and update services.zrefresh [contract|config])rH   rR   rS   targetr   r   r\   Na-  Target to refresh. `ua refresh contract` will update contract details from the server and perform any updates necessary. `ua refresh config` will reload /etc/ubuntu-advantage/uaclient.conf and perform any changes necessary. `ua refresh` is the equivalent of `ua refresh config && ua refresh contract`.)choicesr]   defaultr^   )	r   r*   rT   r9   rU   r   rV   rW   r_   )rX   r   r   r   refresh_parserG  s    r~   c             K   s8   t jtj| js&dj| j}tj|tj|| j dS )NzWError: issue "{}" is not recognized.
Usage: "ua fix CVE-yyyy-nnnn" or "ua fix USN-nnnn"r   )	rematchr   ZCVE_OR_USN_REGEXrx   r9   r   UserFacingErrorZfix_security_issue_id)r=   r>   r?   rL   r   r   r   
action_fixb  s    
r   c             C   s<   t jtdd}|| _d| _d| _d| j_| jdddd | S )	z4Build or extend an arg parser for detach subcommand.detach)rH   rR   z3Detach this machine from Ubuntu Advantage services.rS   z--assume-yes
store_truez;do not prompt for confirmation before performing the detach)ri   r^   )	rT   r9   rU   r   r   r*   rV   rW   r_   )rX   r   r   r   r   detach_parsern  s    r   c             C   s   t jtdd}|| _d| _d| _d| j_| jdddd	jd
j	t
j d | jddttd djtd d | jdddd | S )z2Build or extend an arg parser for help subcommand.zhelp [service])rH   rR   r^   z=Provide detailed information about Ubuntu Advantage services.	ArgumentsrF   storer\   z-a service to view help output for. One of: {}z, )ri   r]   r^   z--formatr   z1output help in the specified format (default: {}))ri   r|   r}   r^   z--allr   z(Allow the visualization of beta services)ri   r^   )rT   r9   rU   r   r   r*   _positionalsrW   r_   r)   r   valid_servicesSTATUS_FORMATS)rX   r   r   r   r   help_parser}  s.    r   c             C   sv   t jtdd}d| _|| _d| _d| j_d| j_| j	ddd	d
jdj
tj d | j	dddd | j	dddd | S )z4Build or extend an arg parser for enable subcommand.zenable <service> [<service>])rH   rR   z#Enable an Ubuntu Advantage service.enabler   rS   rF   r   +zBthe name(s) of the Ubuntu Advantage services to enable. One of: {}z, )ri   r]   r^   z--assume-yesr   z;do not prompt for confirmation before performing the enable)ri   r^   z--betaz allow beta service to be enabled)rT   r9   rU   r*   r   r   r   rW   rV   r_   r)   r   r   )rX   r   r   r   r   enable_parser  s(    
r   c             C   sf   t jtdd}d| _|| _d| _d| j_d| j_| j	ddd	d
jdj
tj d | j	dddd | S )z5Build or extend an arg parser for disable subcommand.zdisable <service> [<service>])rH   rR   z$Disable an Ubuntu Advantage service.disabler   rS   rF   r   r   zBthe name(s) of the Ubuntu Advantage services to disable One of: {}z, )ri   r]   r^   z--assume-yesr   z<do not prompt for confirmation before performing the disable)ri   r^   )rT   r9   rU   r*   r   r   r   rW   rV   r_   r)   r   r   )rX   r   r   r   r   disable_parser  s$    
r   c             C   s   t jtdd}|| _d| _d| _tj| _t	j
d| _| jddddd	 | jd
dttd djtd d | jdddd d| j_| S )z4Build or extend an arg parser for status subcommand.r	   )rH   rR   z<Output the status information for Ubuntu Advantage services.u          Report current status of Ubuntu Advantage services on system.

        This shows whether this machine is attached to an Ubuntu Advantage
        support contract. When attached, the report includes the specific
        support contract details including contract name, expiry dates, and the
        status of each service on this system.

        The attached status output has four columns:

        * SERVICE: name of the service
        * ENTITLED: whether the contract to which this machine is attached
          entitles use of this service. Possible values are: yes or no
        * STATUS: whether the service is enabled on this machine. Possible
          values are: enabled, disabled, n/a (if your contract entitles
          you to the service, but it isn't available for this machine) or — (if
          you aren't entitled to this service)
        * DESCRIPTION: a brief description of the service

        The unattached status output instead has three columns. SERVICE
        and DESCRIPTION are the same as above, and there is the addition
        of:

        * AVAILABLE: whether this service would be available if this machine
          were attached. The possible values are yes or no.
        z--waitr   FzBlock waiting on ua to complete)ri   r}   r^   z--formatr   r   z3output status in the specified format (default: {}))ri   r|   r}   r^   z--allz(Allow the visualization of beta services)ri   r^   rS   )rT   r9   rU   r   r*   r   r0   RawDescriptionHelpFormatterr   textwrapdedentr_   r   rV   rW   )rX   r   r   r   r   status_parser  s2    r   c            C   s*   t j|  }|||d}|j }|j  |S )a=  Perform the disable action on a named entitlement.

    :param entitlement_name: the name of the entitlement to enable
    :param cfg: the UAConfig to pass to the entitlement
    :param assume_yes:
        Assume a yes response for any prompts during service enable

    @return: True on success, False otherwise
    )
assume_yes)r   ENTITLEMENT_CLASS_BY_NAMEr   r	   )Zentitlement_namer>   r   ent_clsentitlementretr   r   r   _perform_disable  s
    

r   z	List[str])rK   c             C   sB   g }x | D ]}|t jkr
|j| q
W tt| t| }||fS )zReturn a list of valid entitlement names.

    :param names: List of entitlements to validate
    :return: a tuple of List containing the valid and invalid entitlements
    )r   r   appendr(   ra   )rK   entitlements_foundent_nameentitlements_not_foundr   r   r   get_valid_entitlement_names/  s    

r   c             K   sd   t  }|j d jd }|j d jj }| j|kr`|j d jd j  tjdjdj	|dS )zGPerform the config action.

    :return: 0 on success, 1 otherwise
    r   r   z
<command> must be one of: {}z, N)

get_parser_get_positional_actionsr|   keysrR   r+   r   r   r9   r)   )r=   r>   r?   rX   	subparserZvalid_choicesr   r   r   action_config@  s    
r   c             K   s   | j rr| j tjkrRdj| j djtj}|jdd }tjtj	|t
jd| dtdj| j t|| j d d	S ttd
d tjD d }d| d }x&tjD ]}t|j|t||d qW dS )zPerform the 'config show' action optionally limit output to a single key

    :return: 0 on success
    :raise UserFacingError: on invalid keys
    z
'{}' must be one of: {}z, :r    )widthZsubsequent_indentz{key} {value})r[   valuer   c             S   s   g | ]}t |qS r   )len).0xr   r   r   
<listcomp>g  s    z&action_config_show.<locals>.<listcomp>   z{key: <z	} {value}N)r[   r   rc   r9   r)   findr   r   r   Zfill	ua_statusZPRINT_WRAP_WIDTHprintrJ   r1   max)r=   r>   r?   rL   Zindent_positionZ	col_widthZrow_tmplr[   r   r   r   rm   O  s"    rm   c             K   s  ddl m} ddlm} ddlm} t }|j d jd }|j d jd }y| j	j
d\}	}
W n. tk
r   |j  tjdj| j	Y nX |	tjkr|j  tjd	jd
jtj|	dkr<|	j
dd }|dkrtj}ntj}tj||
| |	|
i}|f | tjj|}|j \}}|tjjkr|f | nf|	dkr|	j
dd }|dkrftj}ntj}tj||
| |j |j!d}|
||	dd < |f | t"||	|
 dS )zMPerform the 'config set' action.

    @return: 0 on success, 1 otherwise
    r   )setup_apt_proxy)configure_livepatch_proxy)configure_snap_proxyr   ra   =z%
Expected <key>=<value> but found: {}z
<key> must be one of: {}z, 
http_proxyhttps_proxy_Zhttpapt_http_proxyapt_https_proxyr   )r   r      N)r   r   )r   r   )#uaclient.aptr   uaclient.entitlements.livepatchr   uaclient.snapr   r   r   r|   rb   split
ValueErrorr+   r   r   r9   r   rc   r)   r
   ZPROXY_VALIDATION_SNAP_HTTP_URLZPROXY_VALIDATION_SNAP_HTTPS_URLZvalidate_proxyr   	livepatchLivepatchEntitlementapplication_statusr   ApplicationStatusENABLEDZPROXY_VALIDATION_APT_HTTP_URLZPROXY_VALIDATION_APT_HTTPS_URLr   r   setattr)r=   r>   r?   r   r   r   rX   rq   r   Zset_keyZ	set_valueprotocol_typeZvalidate_urlr   livepatch_statusr   r   r   r   rn   m  sR    






rn   c             K   s  ddl m} ddlm} ddlm} | jtjkrzt	 }|j
 d jd }|j
 d jd }|j  tjdjdjtj| jdkr| jjdd }	||	d tjj|}
|
j \}}|tjjkr||	d n6| jdkr|j|jd}d|| jdd < |f | t|| jd dS )zOPerform the 'config unset' action.

    @return: 0 on success, 1 otherwise
    r   )r   )unconfigure_livepatch_proxy)unconfigure_snap_proxyr   re   z
<key> must be one of: {}z, r   r   r   )r   r   r   )r   r   Nr   )r   r   )r   r   )r   r   r   r   r   r   r[   r   rc   r   r   r|   r+   r   r   r9   r)   r   r   r   r   r   r   r   r   r   r   r   )r=   r>   r?   r   r   r   rX   rq   r   r   r   r   r   r   r   r   ro     s2    



ro   z
ua disablec             K   s   t | dg }t|\}}tj}d}x |D ]}|t||| jdM }q(W |rddjtjdd d }	djt	j
|	d	d
d}
tj|jddj||
d|rdS dS )zbPerform the disable action on a list of entitlements.

    @return: 0 on success, 1 otherwise
    rF   T)r   zTry z, )
allow_beta.r   P   F)r   break_long_wordsr   )	operationrH   service_msgr   r   )rJ   r   r   'MESSAGE_INVALID_SERVICE_OP_FAILURE_TMPLr   r   r)   r   r   r   wrapr   r   r9   )r=   r>   r?   rK   r   r   tmplr   r   valid_namesr   r   r   r   action_disable  s"    


r   z	ua enablec             K   s  t tj ytj| W n, tjtjfk
rD   t	j
tjdd Y nX t| dg }t|\}}tj| jd}d}x|D ]}ytj| }	|	|| j| jd}
|
j \}}|j  | r|dk	rt|tjr|jdk	rt |j |jtjjkr|j| ||M }W qv tjk
r* } zt | W Y dd}~X qvX qvW |rdj|}djtjd	| d
 ddd}tj}tj|j ddj||d|rdS dS )z^Perform the enable action on a named entitlement.

    @return: 0 on success, 1 otherwise
    T)exc_inforF   )r   )r   r   Nz, r   zTry r   r   F)r   r   r   )r   rH   r   r   r   )!r   r   ZMESSAGE_REFRESH_CONTRACT_ENABLEr   request_updated_contractr
   UrlErrorr   r   loggingdebug MESSAGE_REFRESH_CONTRACT_FAILURErJ   r   r   r   Zbetar   r   r   r	   
isinstanceZCanEnableFailurer$   reasonZCanEnableFailureReasonZIS_BETAr   r)   r   r   r   r9   )r=   r>   r?   rK   r   r   Zvalid_services_namesr   r   r   r   Zent_retr   er   r   r   r   r   r   action_enable  sP    








r   z	ua detach)returnc             C   s   t || jdS )zXPerform the detach action for this machine.

    @return: 0 on success, 1 otherwise
    )r   )_detachr   )r=   r>   r   r   r   action_detach<  s    r   )r>   r   r   c       	      C   s   g }x0t jD ]&}|| |d}|jddr|j| qW |rzt|dkrJdnd}tdj| x|D ]}tdj|j qbW tj	|d	sdS x|D ]}|j
dd qW tj| }| jd
 }| jd d d }|j|| | j  tj|  ttj dS )a=  Detach the machine from the active Ubuntu Advantage subscription,

    :param cfg: a ``config.UAConfig`` instance
    :param assume_yes: Assume a yes answer to any prompts requested.
         In this case, it means automatically disable any service during
         detach.

    @return: 0 on success, 1 otherwise
    )r>   r   T)Zsilentr   sr6   z,Detach will disable the following service{}:z    {})r   ZmachineTokenmachineTokenInfocontractInfoidr   )r   ZENTITLEMENT_CLASSESZcan_disabler   r   r   r9   rH   r
   Zprompt_for_confirmationr   r   UAContractClientmachine_tokenZdetach_machine_from_contractZdelete_cacher   update_ua_messagesr   ZMESSAGE_DETACH_SUCCESS)	r>   r   Z
to_disabler   Zentsuffixcontract_clientr   Zcontract_idr   r   r   r   G  s,    






r   )r>   rs   allow_enabler   c             C   s   yt j| ||d W n tjk
rp } z>tj  tj| W dQ R X ttj	 | j
  tj|  dS d}~X n@ tjk
r } z"tj|j | j
  tj|  dS d}~X nX | jd d d }|rttjj|d n
ttj tj|  td| d d	S )
zDCommon functionality to take a token and attach via contract backend)r   Nr   r   r   rH   )contract_name)r=   r>   r   )r   r   r
   r   disable_log_to_consoler   rM   r   r   ZMESSAGE_ATTACH_FAILUREr	   r   r   r   r   ZwarningrL   r   ZMESSAGE_ATTACH_SUCCESS_TMPLr9   Z'MESSAGE_ATTACH_SUCCESS_NO_CONTRACT_NAMEaction_status)r>   rs   r   excr   r   r   r   _attach_with_tokeni  s2    





r   )r>   r   c             C   s(  yt j }W n8 tjk
rD } z| jr0tj| |W Y dd}~X nX t j }| jr| jd}t|t|krxtj| t	d t
| dddkrtjtjtj| }y|j|d}W nV tjk
r } z6|jrd|j  kod	k n  rtjtj|W Y dd}~X nX |r | jd| |d
 S )aI  Detect cloud_type and request a contract token from identity info.

    :param cfg: a ``config.UAConfig`` instance

    :raise NonAutoAttachImageError: When not on an auto-attach image type.
    :raise UrlError: On unexpected connectivity issues to contract
        server or inability to access identity doc from metadata service.
    :raise ContractAPIError: On unexpected errors when talking to the contract
        server.
    :raise NonAutoAttachImageError: If this cloud type does not have
        auto-attach support.

    :return: contract token obtained from identity doc
    Nzinstance-idz:Re-attaching Ubuntu Advantage subscription on new instanceT)r   r   )instancei  i  ZcontractToken)r   Zcloud_instance_factoryr   r   rI   rP   Zget_instance_idZ
read_cacher1   r   r   r   Z!MESSAGE_DETACH_AUTOMATION_FAILUREr   r   Z"request_auto_attach_contract_tokenZContractAPIErrorcodeZNonAutoAttachImageErrorZMESSAGE_UNSUPPORTED_AUTO_ATTACHr8   )r>   r   r   Zcurrent_iidZprev_iidr   ZtokenResponser   r   r   '_get_contract_token_from_cloud_identity  s6    



 r   zua auto-attachc             C   sD   t j|jdd}|r.d}tj| t| dS t|}t||ddS )Nzfeatures.disable_auto_attach)r   Zpath_to_valuez8Skipping auto-attach. Config disable_auto_attach is set.r   T)rs   r   )r
   Zis_config_value_truer>   r   r   r   r   r   )r=   r>   Zdisable_auto_attachrL   rs   r   r   r   action_auto_attach  s    
r   z	ua attachc             C   s$   | j stjtjt|| j | jdS )N)rs   r   )rs   r   r   r   ZMESSAGE_ATTACH_REQUIRES_TOKENr   rt   )r=   r>   r   r   r   action_attach  s
    r   c           	   C   s  d} t }g }g }ttjj }x|D ]\}}|jr@dj|j}nd}| j||j|d}t|dkrj|g}	nJg }
|}x,t|dkr|j	dd\}}|
j
d| qtW |d	 dj|
 g}	|jr|j|	 q$|j|	 q$W tttjtjtd
dtjtd
d|||d}|jdddd |jddt djtd d|j_|jdddd}d|_|jddd}t| |jtd |jddd}t| |jtd |jd d!d}t | |jt!d |jd"d#d}t"| |jt#d |jd$d%d}t$| |jt%d |jd&d'd}t&| |jt'd |jd(d)d}|jt(d t)| |jd*d+d}t*| |jt+d |jd,d-d}|jt,d t-| |jd.d/d}|jt.d t/| |jddjtd}|jt0d |S )0Nz - {name}: {description}{url}z ({})r6   )rH   r*   urlr   r   r   r   z
   z	<command>)rH   rR   )r   r   r   r   r   r   r   z--debugr   z&show all debug log messages to console)ri   r^   z	--versionr   zshow version of {})ri   r   r^   rS   zAvailable CommandsrR   )rW   rh   rf   Trr   z7attach this machine to an Ubuntu Advantage subscription)r^   )ri   zauto-attachz+automatically attach on supported platformsr   z5manage Ubuntu Advantage configuration on this machiner   z9remove this machine from an Ubuntu Advantage subscriptionr   z;disable a specific Ubuntu Advantage service on this machiner   z:enable a specific Ubuntu Advantage service on this machinerw   z=check for and mitigate the impact of a CVE/USN on this systemr^   z9show detailed information about Ubuntu Advantage servicesrz   z!refresh Ubuntu Advantage servicesr	   z/current status of all Ubuntu Advantage services)1__doc__r(   r   r   itemsZhelp_doc_urlr9   r*   r   rsplitinsertr)   Zis_betaextendr   rU   r0   r   rT   EPILOG_TMPLr_   get_versionrV   rW   rj   Zrequiredrk   rv   rl   r   rY   r   rq   r   r   r   r   r   r   r   r   ry   r   action_helpaction_refreshr~   r   r   print_version)Zservice_line_tmplr   r   r   Zsorted_classesrH   r   r   Zservice_lineZservice_infoZwrapped_wordslineZwrapped_wordrX   rp   Zparser_attachZparser_auto_attachZparser_configZparser_detachZparser_disableZparser_enableZ
parser_fixZparser_helpZparser_refreshZparser_statusZparser_versionr   r   r   r     s    



r   c             C   s  |st j }| r| jnd}|j|d}tjjj}t|d |k}| r| j	r|rx2|d |krt
ddd tjd |j|d}qPW t
d | r| jdkrt
tj| nX| r| jd	krt
tj| n:tj|}tjjd ksd
tjjj kr|jdd}t
| dS )NF)	show_betaZexecution_statusr   r6   )endr   r   r   zUTF-8u   —-r   )r   UAConfigallr	   r   ZUserFacingConfigStatusZACTIVEr   boolwaitr   timeZsleepr9   Zformat_json_statusZformat_yaml_statusZformat_tabularr!   stdoutencodingupperreplace)r=   r>   r  r	   Zactive_valueZconfig_activeoutputr   r   r   r   \  s,    


r   c             C   s   |d krt j }tj|jdS )N)features)r   r  r   r   r  )_args_cfgr   r   r   r   {  s    r   c             C   s   t t| | d S )N)r   r   )r  r  r   r   r   r    s    r  )r>   c             C   sh   y|j   W nL tk
rX } z0tj  tj| W d Q R X tjtj	W Y d d }~X nX t
tj d S )N)Zprocess_configRuntimeErrorr
   r   r   rM   r   r   r   ZMESSAGE_REFRESH_CONFIG_FAILUREr   ZMESSAGE_REFRESH_CONFIG_SUCCESS)r=   r>   r   r   r   r   _action_refresh_config  s    
r  c             C   sl   yt j| W nN tjk
r\ } z0tj  tj| W d Q R X tjt	j
W Y d d }~X nX tt	j d S )N)r   r   r
   r   r   r   rM   r   r   r   r   r   Z MESSAGE_REFRESH_CONTRACT_SUCCESS)r  r>   r   r   r   r   _action_refresh_contract  s    
r  z
ua refreshc             C   s@   | j d ks| j dkrt| | | j d ks2| j dkr<t| | dS )Nr   r   r   )r{   r  r  )r=   r>   r   r   r   r     s
    

r   c             C   s   | j }| j}|s"t j|d dS |s.tj }|j|}| jdkrRtt	j
| n*x(|j D ]\}}tdj|j | q\W dS )N)r,   r   r   z{}:
{}
)rF   r  r   r+   r   r  r^   r9   r   r   dumpsr   rW   )r=   r>   rF   r,   Zhelp_responser[   r   r   r   r   r     s    

r   c             C   s  |dkrt jd }tj }tjt}tj }|j| d}xT|j	D ]J}t
|drBt
|jdrB|jjdkrB|j|  |j| |jd d}P qBW |stjtj}|j| |j|  |jd |j| tj d	krtj|}	|	j  |	jd
 tj|}
|
j| |
j| |j|
 dS )z3Setup console logging and debug logging to log_fileNlog_fileFstreamrH   z<stderr>consoleTr   i  )r   ZCONFIG_DEFAULTSr
   ZLogFormatterr   Z	FormatterDEFAULT_LOG_FORMATZ	getLoggerZsetLevelZhandlershasattrr  rH   ZsetFormatterZset_nameZStreamHandlerr!   r"   Z
addHandlerr:   rD   pathlibZPathZtouchchmodZFileHandler)console_level	log_levelr  Zconsole_formatterZlog_formatterrootZstderr_foundZhandlerr  Zlog_file_pathZfilehandlerr   r   r   setup_logging  s:    














r!  c                s    fdd}|S )Nc                 s  y
 | |S  t k
rb   tj  tjd W d Q R X tdtjd trRtd tj	d Y n tj
k
r0 } zdt|krtj}tjdrtj}t|j|jdtjd nVtj 8 |j|d	}|jrtj}ntj}tj|jf | W d Q R X ttjtjd trtd tj	d W Y d d }~X n tjk
r } zdtj  tj|j W d Q R X td
j|jtjd trt|tjstd tj	|j W Y d d }~X n\ tk
r   tj  tjd W d Q R X trtd ttjtjd tj	d Y nX d S )NKeyboardInterruptzInterrupt received; exiting.)r&   r5   r   ZCERTIFICATE_VERIFY_FAILEDzca-certificates)r   )r   r%   z{}z&Unhandled exception, please file a bug)r"  r
   r   r   r%   r   r!   r"   r<   r#   r   r1   r   Z.MESSAGE_SSL_VERIFICATION_ERROR_CA_CERTIFICATESZis_installedZ-MESSAGE_SSL_VERIFICATION_ERROR_OPENSSL_CONFIGr9   r   Z$LOG_CONNECTIVITY_ERROR_WITH_URL_TMPLZLOG_CONNECTIVITY_ERROR_TMPLrM   ZMESSAGE_CONNECTIVITY_ERRORr   r   rL   r   r7   Z	exit_code	ExceptionZMESSAGE_UNEXPECTED_ERROR)r=   r?   r   r   Zmsg_argsZmsg_tmpl)funcr   r   rB     sP    





z#main_error_handler.<locals>.wrapperr   )r$  rB   r   )r$  r   main_error_handler  s    1r%  c       
      C   s   | s
t j} t }| dd  }|s:|j  td t jd |j|d}tj }|j	}|j
}tj||d |j}|jrztjntj}t|||j tjtjd|   dd ttjj D }	|	rtjtjd|	  |j||S )	Nr   z%Try 'ua --help' for more information.)r=   )r   r   zExecuted with sys.argv: %rc             S   s:   g | ]2\}}|j  tks*|jd s*|dkrdj||qS )ZUA_FEATURESZUA_CONFIG_FILEz{}={})lowerr   
startswithr9   )r   kvr   r   r   r   2  s   
zmain.<locals>.<listcomp>z*Executed with UA environment variables: %r)r!   argvr   r    r   r#   
parse_argsr   r  r   r   r
   Zconfigure_web_proxyr  r   r   DEBUGINFOr!  r  Zredact_sensitive_logsr(   r:   environr   ri   )
Zsys_argvrX   Zcli_argumentsr=   r>   r   r   r  r  Zua_environmentr   r   r   main  s2    
r/  __main__)N)N)NN)NN)N)N)Yr   r0   	functoolsr   r   r   r:   r  r   r!   r   r
  Ztypingr   ImportErrorZuaclientr   r   r   r   r   r	   r   r
   r   Zuaclient.cloudsr   Zuaclient.defaultsr   rU   rT   r   ZSTATUS_HEADER_TMPLru   r  r   r<   ArgumentParserr   rC   rE   rO   rQ   rY   r`   rd   rg   rq   rv   ry   r~   r   r   r   r   r   r   r   r   r   rm   rn   ro   Z&MESSAGE_ENABLE_FAILURE_UNATTACHED_TMPLr   r   intr   r  r  r   r1   r   r   r   r   r   r   r   r  r  r  r   r   r!  r%  r/  r-   r#   r   r   r   r   <module>   s   
(
'
'A>'$B#%2~



$5&
