o
    K&bP                     @   s,  d Z ddlZddlZddlZddlZddlZddl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mZmZ ddlZddlmZmZmZmZmZmZmZmZmZmZmZ ddlm Z! ddlm"Z"m#Z# ddl$m%Z% dd	l$m&Z& dd
l'm(Z(m)Z) ddl*m+Z+m,Z,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 dZ3dZ4dZ5dZ6dZ7dZ8g dZ9dZ:dZ;e< Z=G dd dej>Z?dddZ@dd ZAdd ZBddd ZCd!d" ZDd#d$ ZEd%d& ZFd'd( ZGd)d* ZHd+d, ZId-d. ZJd/d0 ZKd1d2 ZLd3d4 ZMd5d6 ZNd7d8 ZOd9d: ZPd;d< ZQd=d> ZRd?d@ ZSdAdB ZTdCdD ZUdEdFdGdHZVdIeeW fdJdKZXdLdM ZYdNdO ZZeAdPdQ Z[eAdRdS Z\eBeAeCej]e@dTdUdV Z^dWe_dXej`fdYdZZaeBeAeCej]e@d[d\d] ZbeBeAeC e@d^dXecfd_d`Zddaejedbe_dXecfdcddZfdaejedXdfdedfZgeAe@dgdhdi ZheDeAe@djdkdl Zi	ddmeWdneec dXdfdodpZjeAdaejefdqdrZkdsdt Zldudv ZmddwdxZnddydzZodaejefd{d|ZpeC daejefd}d~ZqeAe@ddaejefddZrdd ZsdddZtdd Zudd ZvevdddZwexdkreyew  dS dS )z8Client to manage Ubuntu Advantage services on a machine.    Nwraps)ListOptionalTuple)actionsconfigcontractentitlementsevent_logger
exceptionsjobslockmessagessecuritysecurity_status)status)utilversion)AutoAttachCloudInstance)identity)AttachActionsConfigFileIncorrectTypeError)CLOUD_BUILD_INFOCONFIG_FIELD_ENVVAR_ALLOWLISTDEFAULT_CONFIG_FILEPRINT_WRAP_WIDTH)LIVEPATCH_CMD)update_apt_and_motd_messagesZ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)s)Ztabularjsonyamlzua_logs.tar.gz)zua-timer.servicezua-timer.timerzua-auto-attach.pathzua-auto-attach.servicezua-reboot-cmds.servicezua-license-check.pathzua-license-check.servicezua-license-check.timerc                       sh   e Zd Zdddejdfdef fddZdd Zd fdd		Ze	d
e
ee ee f fddZ  ZS )UAArgumentParserN	base_descc                    s   t  j||||d || _d S )N)progusageepilogformatter_class)super__init__r"   )selfr#   r$   r%   r&   r"   	__class__ ./usr/lib/python3/dist-packages/uaclient/cli.pyr(   [   s   
zUAArgumentParser.__init__c                 C   s    |  tj | d|d  d S )N   
)print_usagesysstderrexit)r)   messager,   r,   r-   errorl   s   zUAArgumentParser.errorFc                    sP   | j rt \}}t|}|rt|| }d| j g| | _t j|d d S )Nr/   file)r"   r!   _get_service_descriptionssortedjoindescriptionr'   
print_help)r)   r7   show_allnon_beta_services_descbeta_services_descZservice_descriptionsr*   r,   r-   r<   p   s   
zUAArgumentParser.print_helpreturnc            	   	   C   s   d} g }g }t t }|D ]I}z	t|d }W n
 tjy$   Y qw |d|d }|j	r7d
|j	}nd}tj| j
||j|dtdddd	}|jrS|| q|| q||fS )
Nz - {name}: {description}{url}nameZpresentedAsz ({}) )rA   r;   urlz   F)widthsubsequent_indentbreak_long_wordsbreak_on_hyphens)r	   Zget_available_resourcesr   UAConfigr
   entitlement_factoryr   ZEntitlementNotFoundErrorgetZhelp_doc_urlformattextwrapfillr;   r   Zis_betaappend)	Zservice_info_tmplr>   r?   Z	resourcesZresourceent_clsZpresentation_namerC   Zservice_infor,   r,   r-   r8      s:   z*UAArgumentParser._get_service_descriptions)NF)__name__
__module____qualname__argparseHelpFormatterstrr(   r5   r<   staticmethodr   r   r8   __classcell__r,   r,   r*   r-   r!   Z   s    (r!   c                        fdd}|S )z1Decorator asserting exclusive access to lock filec                       t   fdd}|S )Nc                    sF   t j| d  |d| i|}W d    |S 1 sw   Y  |S )N)cfglock_holderrZ   )r   ZSingleAttemptLock)rZ   argskwargsZretval)fr[   r,   r-   new_f   s   
z0assert_lock_file.<locals>.wrapper.<locals>.new_fr   r^   r_   r[   r^   r-   wrapper   s   z!assert_lock_file.<locals>.wrapperr,   )r[   rc   r,   ra   r-   assert_lock_file   s   	rd   c                       t   fdd}|S )zDecorator asserting root userc                     s"   t  dkr
t  | i |S )Nr   )osgetuidr   ZNonRootUserError)r\   r]   rb   r,   r-   r_      s   zassert_root.<locals>.new_fr   r`   r,   rb   r-   assert_root   s   rh   c                    re   )z>Decorator to verify if correct params are used for json formatc                    sX   | s | g|R i |S | j dkr!| js!tj}tj|j|jd | g|R i |S )Nr   msgmsg_code)rK   
assume_yesr   ZJSON_FORMAT_REQUIRE_ASSUME_YESr   UserFacingErrorrj   rA   )cmd_argsr\   r]   rj   rb   r,   r-   r_      s   z&verify_json_format_args.<locals>.new_fr   r`   r,   rb   r-   verify_json_format_args   s   
ro   c                    rX   )zDecorator asserting attached config.

    :param unattached_msg_tmpl: Optional msg template to format if raising an
        UnattachedError
    c                    rY   )Nc                    sV   |j s!rt| dd}jd|d}t|}|t }| | fd|i|S )NserviceNone, rA   rZ   )is_attachedgetattrrK   r:   r   ZUnattachedError)r\   rZ   r]   namesrj   	exception)r^   unattached_msg_tmplr,   r-   r_      s   
z/assert_attached.<locals>.wrapper.<locals>.new_fr   r`   rx   rb   r-   rc      s   z assert_attached.<locals>.wrapperr,   )rx   rc   r,   ry   r-   assert_attached   s   rz   c                    re   )z&Decorator asserting unattached config.c                    s   |j rt| | |dS )NrZ   )rt   r   AlreadyAttachedErrorr\   rZ   rb   r,   r-   r_      s   
z"assert_not_attached.<locals>.new_fr   r`   r,   rb   r-   assert_not_attached   s   r~   c                 C   s*   d| _ d| _tjt| j d| _d| j_| S )z9Build or extend an arg parser for auto-attach subcommand.auto-attachzDAutomatically attach an Ubuntu Advantage token on Ubuntu Pro images.rA   commandFlags)r#   r;   
USAGE_TMPLrK   NAMEr$   
_optionalstitleparserr,   r,   r-   auto_attach_parser   s   r   c                 C   s2   d| _ d| _tjt| j d| _| jdddd | S )z<Build or extend an arg parser for 'collect-logs' subcommand.collect-logsz?Collect UA logs and relevant system information into a tarball.r   z-oz--outputzEtarball where the logs will be stored. (Defaults to ./ua_logs.tar.gz)help)r#   r;   r   rK   r   r$   add_argumentr   r,   r,   r-   collect_logs_parser  s   r   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]r   showz(Show customisable configuration settingskey?z6Optional key or key(s) to show configuration settings.nargsr   )r   rK   r   r$   r#   r;   r   r   r,   r,   r-   config_show_parser  s   r   c                 C   sD   t jtdd| _d| _d| _d| j_| jddd	t
jd	 | S )
z:Build or extend an arg parser for 'config set' subcommand.zset <key>=<value>r   setz5Set and apply Ubuntu Advantage configuration settingsr   key_value_pairzQkey=value pair to configure for Ubuntu Advantage services. Key must be one of: {}rr   r   )r   rK   r   r$   r#   r;   r   r   r   r:   r   UA_CONFIGURABLE_KEYSr   r,   r,   r-   config_set_parser!  s   
	r   c                 C   sF   t jtdd| _d| _d| _| jdddtj	dd d	| j
_| S )
z<Build or extend an arg parser for 'config unset' subcommand.zunset <key>r   unsetz,Unset Ubuntu Advantage configuration settingr   zEconfiguration key to unset from Ubuntu Advantage services. One of: {}rr   )r   metavarr   )r   rK   r   r$   r#   r;   r   r:   r   r   r   r   r   r,   r,   r-   config_unset_parser5  s   r   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>r   r   z%Manage Ubuntu Advantage configurationr   Available Commandsr   rB   r   destr   r   z2show all Ubuntu Advantage configuration setting(s)r   actionr   z*set Ubuntu Advantage configuration settingr   z,unset Ubuntu Advantage configuration setting)r   rK   r   r$   r#   r;   r   r   add_subparsers
add_parserset_defaultsaction_config_showr   action_config_setr   action_config_unsetr   )r   
subparsersZparser_showZ
parser_setZparser_unsetr,   r,   r-   config_parserF  s.   r   c                 C   s~   t jtdd| _d| _d| _d| j_| jdddt	d	 | jd
dddd | jdt
ddd | jddddgddd | S )z4Build or extend an arg parser for attach subcommand.zattach <token>r   attachz_Attach this machine to Ubuntu Advantage with a token obtained from https://ubuntu.com/advantager   tokenr   z6token obtained for Ubuntu Advantage authentication: {}r   z--no-auto-enablestore_falseauto_enablez4do not enable any recommended services automatically)r   r   r   z--attach-configrzKuse the provided attach config file instead of passing the token on the cli)typer   --formatstoreclir   4output enable in the specified format (default: cli)r   choicesdefaultr   )r   rK   r   r$   r#   r;   r   r   r   UA_AUTH_TOKEN_URLrS   FileTyper   r,   r,   r-   attach_parserc  s>   r   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+>r   fixzLInspect and resolve CVEs and USNs (Ubuntu Security Notices) on this machine.r   security_issuezwSecurity vulnerability ID to inspect and resolve on this system. Format: CVE-yyyy-nnnn, CVE-yyyy-nnnnnnn or USN-nnnn-ddr   	r   rK   r   r$   r#   r;   r   r   r   r   r,   r,   r-   
fix_parser  s   r   c                 C   s"   d| _ d| _| jddddd | S )z=Build or extend an arg parser for security-status subcommand.security-statusz^Show security updates for packages in the system, including all available ESM related content.r   z$Format for the output (json or yaml))r   r    T)r   r   required)r#   r;   r   r   r,   r,   r-   security_status_parser  s   r   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]r   r   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`.)r   r   r   r   )	r#   r;   r   rK   r   r$   r   r   r   r   r,   r,   r-   refresh_parser  s   r   c                K   s>   | j dkrttt| dS ttjt|dd dS )Nr   F)Zdefault_flow_styler   )rK   printr   dumpsr   r    Z	safe_dump)r\   rZ   r]   r,   r,   r-   action_security_status  s   

r   c                K   s:   t tj| jsd| j}t|t|| j}|j	S )NzWError: issue "{}" is not recognized.
Usage: "ua fix CVE-yyyy-nnnn" or "ua fix USN-nnnn")
rematchr   ZCVE_OR_USN_REGEXr   rK   r   rm   Zfix_security_issue_idvalue)r\   rZ   r]   rj   Z
fix_statusr,   r,   r-   
action_fix  s   
r   c                 C   sT   t jtdd}|| _d| _d| _d| j_| jdddd | jd	d
ddgddd | S )z4Build or extend an arg parser for detach subcommand.detachr   z3Detach this machine from Ubuntu Advantage services.r   --assume-yes
store_truez;do not prompt for confirmation before performing the detachr   r   r   r   r   r   r   r   r   r   r$   r,   r,   r-   detach_parser  s$   r   c              
   C   s   t jtdd}|| _d| _d| _d| j_| jdddd	d
	t
 d | jddttd dtd d | jdddd | S )z2Build or extend an arg parser for help subcommand.zhelp [service]r   r   z=Provide detailed information about Ubuntu Advantage services.	Argumentsrp   r   r   z-a service to view help output for. One of: {}rr   r   r   r   r   r   z1output help in the specified format (default: {})r   --allr   (Allow the visualization of beta servicesr   )r   rK   r   r$   r#   r;   _positionalsr   r   r:   r
   valid_servicesSTATUS_FORMATSr   r,   r,   r-   help_parser  s:   	r   c              
   C   s   t jtdd}d| _|| _d| _d| j_d| j_| j	ddd	d
d
t d | j	dddd | j	dddd | j	ddddgddd | S )z4Build or extend an arg parser for enable subcommand.zenable <service> [<service>]r   z#Enable an Ubuntu Advantage service.enabler   r   rp   r   +zBthe name(s) of the Ubuntu Advantage services to enable. One of: {}rr   r   r   r   z;do not prompt for confirmation before performing the enabler   z--betaz allow beta service to be enabledr   r   r   r   r   r   rK   r   r;   r$   r#   r   r   r   r   r:   r
   r   r   r,   r,   r-   enable_parser!  s>   	r   c              
   C   s~   t jtdd}d| _|| _d| _d| j_d| j_| j	ddd	d
d
t d | j	dddd | j	ddddgddd | S )z5Build or extend an arg parser for disable subcommand.zdisable <service> [<service>]r   z$Disable an Ubuntu Advantage service.disabler   r   rp   r   r   zBthe name(s) of the Ubuntu Advantage services to disable One of: {}rr   r   r   r   z<do not prompt for confirmation before performing the disabler   r   r   r   z5output disable in the specified format (default: cli)r   r   r   r,   r,   r-   disable_parserF  s8   	r   c              	   C   s   t jtdd}|| _d| _d| _tj| _t	
d| _| jddddd	 | jd
dttd dtd d | jddddd | jdddd d| j_| S )z4Build or extend an arg parser for status subcommand.r   r   z<Output the status information for Ubuntu Advantage services.uA          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.

        If --simulate-with-token is used, then the output has five
        columns. SERVICE, AVAILABLE, ENTITLED and DESCRIPTION are the same
        as mentioned above, and AUTO_ENABLED shows whether the service is set
        to be enabled when that token is attached.

        If the --all flag is set, beta and unavailable services are also
        listed in the output.
        z--waitr   FzBlock waiting on ua to complete)r   r   r   r   r   r   z3output status in the specified format (default: {})r   z--simulate-with-tokenZTOKENz1simulate the output status using a provided token)r   r   r   r   r   r   r   )r   rK   r   r$   r;   r#   rS   RawDescriptionHelpFormatterr&   rL   dedentr   r   r   r   r   r,   r,   r-   status_parserh  sJ   %r   T)update_statusc                C   s   |   \}}|s2t| j |dur1t|tjr1|jdur1t|jj	 tj
|jj	|jj| jd nt| j |r>|  |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
    N	error_msg
error_coderp   )r   eventservice_failedrA   
isinstance	ua_statusZCanDisableFailurer4   inforj   r5   service_processedr   )entitlementrZ   rl   r   retreasonr,   r,   r-   _perform_disable  s$   


r   rv   c                 C   sF   g }| D ]}|t jdddv r|| q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
    T)
allow_betaZ	all_names)r
   r   rN   r9   r   )rv   entitlements_foundent_nameentitlements_not_foundr,   r,   r-   get_valid_entitlement_names  s   
r   c                K   sd   t  }| d jd }| d j }| j|vr0| d jd   tdd	|dS )zGPerform the config action.

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

get_parser_get_positional_actionsr   keysr   r<   r   rm   rK   r:   )r\   rZ   r]   r   	subparserZvalid_choicesr,   r,   r-   action_config  s   
r   c                K   s   | j r8| j tjvr(d| j dtj}|dd }ttj	|t
d| dtdj| j t|| j d d	S ttd
d tjD d }d| d }tjD ]}t|j|t||d qOd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: {}rr   :r.    )rD   rE   z{key} {value})r   r   r   c                 S   s   g | ]}t |qS r,   )len).0xr,   r,   r-   
<listcomp>  s    z&action_config_show.<locals>.<listcomp>   z{key: <z	} {value}N)r   r   r   rK   r:   findr   rm   rL   rM   r   r   ru   rU   max)r\   rZ   r]   rj   Zindent_positionZ	col_widthZrow_tmplr   r,   r,   r-   r     s,   
r   c             	   K   s  ddl m} ddlm} ddlm} t }| d jd }| d jd }z
| j	
d\}	}
W n tyE   |  td| j	w |	tjvr[|  td	d
tj|	dv r|	
dd }|dkrntj}ntj}t||
| |	|
i}|di | tj|}| \}}|tjjkr|di | nb|	dv r|	
dd }|dkrtj}ntj}t||
| |j |j!d}|
||	dd < |di | n.|	dv rzt"|
}
|
dk rtd|	W n ty   |  t#d td|	|
w t$||	|
 dS )zMPerform the 'config set' action.

    @return: 0 on success, 1 otherwise
    r   setup_apt_proxy)configure_livepatch_proxy)configure_snap_proxyr   r   =z%
Expected <key>=<value> but found: {}
<key> must be one of: {}rr   
http_proxyhttps_proxy_Zhttpapt_http_proxyapt_https_proxyr      N)Zupdate_messaging_timerZupdate_status_timerZmetering_timerzInvalid interval for {}rB   zECannot set {} to {}: <value> for interval must be a positive integer.r,   )%uaclient.aptr  uaclient.entitlements.livepatchr  uaclient.snapr  r   r   r   r   split
ValueErrorr<   r   rm   rK   r   r   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  intr   setattr)r\   rZ   r]   r  r  r  r   r   r   Zset_keyZ	set_valueprotocol_typeZvalidate_urlr   livepatch_statusr  r,   r,   r-   r     s|   


r   c                K   s  ddl m} ddlm} ddlm} | jtjvr=t	 }|
 d jd }|
 d jd }|  tddtj| jd	v rg| jd
d }	||	d tj|}
|
 \}}|tjjkrf||	d n| jdv r|j|jd	}d|| jdd < |di | t|| jd dS )zOPerform the 'config unset' action.

    @return: 0 on success, 1 otherwise
    r   r  )unconfigure_livepatch_proxy)unconfigure_snap_proxyr   r   r  rr   r  r  )r  r  Nr  r,   )r  r  r  r  r  r  r   r   r   r   r   r   r<   r   rm   rK   r:   r  r
   r  r  r  r   r  r  r  r  r  )r\   rZ   r]   r  r  r  r   r   r   r  r   r  r  r,   r,   r-   r   j  s:   




r   z
ua disablec                K   s   t | dg }t|\}}d}|D ]}t|}||| jd}	|t|	|| jdM }q|rOddtjdd d }
dtj	|
d	d
d
d}t
jdd||dt  |rWdS dS )zbPerform the disable action on a list of entitlements.

    @return: 0 on success, 1 otherwise
    rp   Trl   Try rr   r   .r/   P   FrD   rF   rG   r   Z	operationrA   service_msgr   r   )ru   r   r
   rI   rl   r   r:   r   rL   wrapr   ZInvalidServiceToDisableErrorr   process_events)r\   rZ   r]   rv   r   r   r   r   rO   entvalid_namesr'  r,   r,   r-   action_disable  s>   	
r,  r   r@   c                C   sN   t j|d}d|}dtjd| d dddd}tjjd	d| |d
S )z{
    Constructs the MESSAGE_INVALID_SERVICE_OP_FAILURE message
    based on the attempted services and valid services.
    r"  rr   r/   r!  r#  r$  Fr%  r   r&  )r
   r   r:   rL   r(  r   ZINVALID_SERVICE_OP_FAILURErK   )r   r   Zvalid_services_namesr+  r'  r,   r,   r-   -_create_enable_entitlements_not_found_message  s   

	r-  z	ua enablec                K   s  t tj zt| W n tjtjfy)   t	j
tjdd t jtjd Y nw t| dg }t|\}}d}|D ]}z]tj||| j| jd\}}	|  |s|	durt|	tjr|	jdurrt |	jj t j|	jj|	jj|d |	jtjjkr~|| n|rt j|d n|s|	du rt j |d ||M }W q: tjy }
 zt |
j t j|
j|
j!|d d	}W Y d}
~
q:d}
~
ww |rt"|| jd
}t #| tj|j|jdt $  |rdS dS )z^Perform the enable action on a named entitlement.

    @return: 0 on success, 1 otherwise
    T)exc_info)Zwarning_msgrp   rl   r   Nr   )rp   Fr"  ri   r   r   )%r   r   r   ZREFRESH_CONTRACT_ENABLEr	   request_updated_contractr   UrlErrorrm   loggingdebugREFRESH_CONTRACT_FAILUREZwarningru   r   r   enable_entitlement_by_namerl   Zbetar   r   r   CanEnableFailurer4   rj   r5   rA   r   ZCanEnableFailureReasonZIS_BETArN   r   r   rk   r-  Zservices_failedr)  )r\   rZ   r]   rv   r   r   r   r   ent_retr   erj   r,   r,   r-   action_enable  sn   	





r9  z	ua detachc                C   s   t || jdS )zXPerform the detach action for this machine.

    @return: 0 on success, 1 otherwise
    r   )_detachrl   r}   r,   r,   r-   action_detach  s   	r;  rZ   rl   c                 C   s   g }t jD ]}|| |d}|jdd\}}|r|| q	 |jdd d |rHt|dkr0dnd	}td
| |D ]}td|j	 q<t
j|dsPdS |D ]
}t|| |dd qR|   t|  t|  ttj t  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
    )rZ   rl   T)Zignore_dependent_servicesc                 S   s
   t | jS N)r   Zdependent_services)r*  r,   r,   r-   <lambda>K  s   
 z_detach.<locals>.<lambda>)r   r   srB   z,Detach will disable the following service{}:z    {}r   F)rl   r   r   )r
   ENTITLEMENT_CLASSESZcan_disablerN   sortr   r   r   rK   rA   r   Zprompt_for_confirmationr   Zdelete_cacher   Z"enable_license_check_if_applicabler   r   ZDETACH_SUCCESSr)  )rZ   rl   Z
to_disablerO   r*  r   r  suffixr,   r,   r-   r:  (  s4   



r:  c                 C   s   d }| j r| j di di d}|r ttjj|d nttj t	|  t
| \}}t|}tt| t  d S )NZmachineTokenInfoZcontractInforA   )contract_name)Zmachine_tokenrJ   r   r   r   ZATTACH_SUCCESS_TMPLrK   ZATTACH_SUCCESS_NO_CONTRACT_NAMEr   Z#disable_license_check_if_applicabler   r   r   format_tabularr   handle_unicode_charactersr)  )rZ   rB  r   Z_retoutputr,   r,   r-   _post_cli_attacha  s    

rF  zua auto-attachc             
   C   s  t j|jdd}|rd}t| t| dS d }zt }W nD tj	yc } z7|j
r0t|t|tjr<ttjt|tjrHttjt|tjrYttjj|jdttjd }~ww |slttjt }|j
r|d}t|t|krtt|td t|dd	dkrttjzt|| W n tj y   t!"tj# Y d
S  tjy   Y d
S w t$| dS )Nzfeatures.disable_auto_attach)r   Zpath_to_valuez8Skipping auto-attach. Config disable_auto_attach is set.r   )
cloud_typezinstance-idz:Re-attaching Ubuntu Advantage subscription on new instanceTr   r   )%r   Zis_config_value_truerZ   r2  r3  r   r   Zcloud_instance_factoryr   ZCloudFactoryErrorrt   r|   r   ZCloudFactoryNoCloudErrorrm   r   ZUNABLE_TO_DETERMINE_CLOUD_TYPEZCloudFactoryNonViableCloudErrorZUNSUPPORTED_AUTO_ATTACHZ!CloudFactoryUnsupportedCloudErrorZNonAutoAttachImageErrorZ"UNSUPPORTED_AUTO_ATTACH_CLOUD_TYPErK   rG  Zget_instance_idZ
read_cacherU   ZAlreadyAttachedOnPROErrorr:  ZDETACH_AUTOMATION_FAILUREr   Zauto_attachr1  r   r   ATTACH_FAILURErF  )r\   rZ   Zdisable_auto_attachrj   instancer8  Zcurrent_iidZprev_iidr,   r,   r-   action_auto_attachz  sn   


rJ  z	ua attachc             
   C   s8  | j s| jstjtjjtjjd| j r"| jr"tjtjjtjjd| j r+| j }d }n(zt	
t| j}W n tyL } z
tj| jj|jdd }~ww |j }|j}| joY|d u }z
tj|||d W nG tjy   tj}t|j tj|j|jd t  Y dS  tjy } zt|j tj|j|jd t  W Y d }~dS d }~ww d}	|d ur| jrt|\}
}|
D ]9}tj||ddd\}}|sd}	|d urt|tjr|jd urt|jj tj|jj|jj|d	 qt | q|rt!|dd
}tj|jt"j#d tj|j|jd d}	t$| |	S )Nri   )Zconfig_namer5   )r   allow_enabler   r   r   r   Tr/  r   r"  )	file_type)%r   attach_configr   rm   r   ZATTACH_REQUIRES_TOKENrj   rA   ZATTACH_TOKEN_ARG_XOR_CONFIGr   Z	from_dictr    Z	safe_loadr   ZAttachInvalidConfigFileErrorZenable_servicesr   r   Zattach_with_tokenr1  rH  r   r   r5   r)  rk   r   r5  r   r   r6  r4   r   r-  r1   r2   rF  )r\   rZ   r   Zenable_services_overriderN  r8  rK  rj   excr   foundZ	not_foundrA   r7  r   r,   r,   r-   action_attach  s   



rQ  filenamereturn_codesc              
   C   sj   zt j|  |d\}}W n tjy, } zt d|t| W Y d}~dS d}~ww t || dS )zCHelper which runs a command and writes output or error to filename.)Zrcsz{}-errorN)r   Zsubpr  r   ZProcessExecutionError
write_filerK   rU   )cmdrR  rS  outr  r8  r,   r,   r-   _write_command_output_to_file  s   $rW  c          	   	   C   s  | j pt}t }tdd| tdd| tdtd| tdd| td	d
dd tD d| tD ]}td|d||ddgd qB|j	pYt
|j|j|j|dtgdd tjD R }|D ]}tj|rt|}t|}t|| t|| qqt|d}|j|dd W d    n1 sw   Y  W d    d S W d    d S 1 sw   Y  d S )Nzcloud-idz{}/cloud-id.txtzua status --format jsonz{}/ua-status.jsonz	{} statusz{}/livepatch-status.txtzsystemctl list-timers --allz{}/systemd-timers.txtzxjournalctl --boot=0 -o short-precise {} -u cloud-init-local.service -u cloud-init-config.service -u cloud-config.servicer   c                 S   s   g | ]}d |v rd |qS )z.servicez-u {})rK   )r   r>  r,   r,   r-   r   7  s    z'action_collect_logs.<locals>.<listcomp>z{}/journalctl.txtzsystemctl status {}z	{}/{}.txtr      )rS  zjobs-statusc                 s   s.    | ]}t |tjjr|jj|jd V  qdS )rs   N)
issubclassr
   ZrepoZRepoEntitlementZrepo_list_file_tmplrK   rA   )r   r   r,   r,   r-   	<genexpr>K  s    
z&action_collect_logs.<locals>.<genexpr>zw:gzzlogs/)Zarcname)rE  UA_COLLECT_LOGS_FILEtempfileZTemporaryDirectoryrW  rK   r   r:   UA_SERVICESZcfg_pathr   log_fileZtimer_log_fileZlicense_check_log_fileZ	data_pathr   r
   r?  rf   pathisfiler   Z	load_fileredact_sensitive_logsrT  shutilcopytarfileopenadd)	r\   rZ   Zoutput_fileZ
output_dirrp   Zua_logslogZlog_contentresultsr,   r,   r-   action_collect_logs  sn   






:"ri  c                  C   s0  t } 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
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}	t|	 |	jtd |jd"d#d}
|
jtd t|
 |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}|jt&d t'| |jd	d
td}|jt(d |S ),Nz	<command>r   )r#   r&   r$   r%   r"   z--debugr   z&show all debug log messages to consoler   z	--versionr   zshow version of {})r   r   r   r   r   r   rB   r   Tr   z7attach this machine to an Ubuntu Advantage subscriptionr   r   r   z+automatically attach on supported platformsr   z%collect UA logs and debug informationr   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 machiner   z=check for and mitigate the impact of a CVE/USN on this systemr   z.list available security updates for the systemr   z9show detailed information about Ubuntu Advantage servicesr   z!refresh Ubuntu Advantage servicesr   z/current status of all Ubuntu Advantage services))__doc__r!   r   rS   r   r   rK   EPILOG_TMPLr   get_versionr   r   r   r   r   r   r   rQ  r   rJ  r   ri  r   r   r   r;  r   r,  r   r9  r   r   r   r   r   action_helpaction_refreshr   action_statusr   print_version)r"   r   r   Zparser_attachZparser_auto_attachZparser_collect_logsZparser_configZparser_detachZparser_disableZparser_enableZ
parser_fixZparser_security_statusZparser_helpZparser_refreshZparser_statusZparser_versionr,   r,   r-   r   ]  s   
r   c          	      C   s   |st  }| r| jnd}| r| jnd }tjjj}tj	|||d\}}t
|d |k}| rY| jrY|rY|d |krTtjddd td tj	|||d\}}|d |ks8td t| t|}tt| t  |S )NF)simulate_with_token	show_betaZexecution_statusr#  rB   )endr   )r   rH   allrq  r   ZUserFacingConfigStatusZACTIVEr   r   r   boolwaitr   r   timesleepZset_output_contentrC  r   rD  r)  )	r\   rZ   rr  r   Zactive_valuer   r   Zconfig_activerE  r,   r,   r-   ro    s.   






ro  c                 C   s   |d u rt  }tj|jdS )N)features)r   rH   r   rl  ry  )_argsZ_cfgr,   r,   r-   rl    s   rl  c                 C   s   t t| | d S r<  )r   rl  )rz  rZ   r,   r,   r-   rp    s   rp  c                 C   sr   z|   W n+ ty1 } zt  t| W d    n1 s"w   Y  ttj	d }~ww t
tj d S r<  )Zprocess_configRuntimeErrorr   disable_log_to_consoler2  rw   r   rm   r   ZREFRESH_CONFIG_FAILUREr   ZREFRESH_CONFIG_SUCCESS)r\   rZ   rO  r,   r,   r-   _action_refresh_config  s   
r}  c                 C   sv   zt | W n, tjy3 } zt  t| W d    n1 s$w   Y  tt	j
d }~ww tt	j d S r<  )r	   r0  r   r1  r   r|  r2  rw   rm   r   r4  r   ZREFRESH_CONTRACT_SUCCESS)rz  rZ   rO  r,   r,   r-   _action_refresh_contract  s   
r~  z
ua refreshc                C   s@   | j d u s
| j dkrt| | | j d u s| j dkrt| | dS )Nr   r	   r   )r   r}  r~  r}   r,   r,   r-   rn    s
   

rn  c                C   s~   | j }| j}|st j|d dS |st }||}| jdkr*tt	
| dS | D ]\}}td| | q.dS )N)r=   r   r   z{}:
{}
)rp   rt  r   r<   r   rH   r   rK   r   r   r   itemsr   )r\   rZ   rp   r=   Zhelp_responser   r   r,   r,   r-   rm    s   

rm  c           
      C   s   |du rt  }|j}t }tt}|du rt }|	| g |_
ttj}|| |	|  |d || t dkrqt|}| sV|  |d t|}	|		| |	| |	d ||	 dS dS )z3Setup console logging and debug logging to log_fileNz
ua-consoler   i  zua-file)r   rH   r^  r   ZLogFormatterr2  Z	FormatterDEFAULT_LOG_FORMATZ	getLoggerZsetLevelhandlersZStreamHandlerr1   r2   ZsetFormatterZset_nameZ
addHandlerrf   rg   pathlibZPathexistsZtouchchmodZFileHandler)
console_level	log_levelr^  loggerrZ   Zconsole_formatterZlog_formatterZconsole_handlerZlog_file_pathZfile_handlerr,   r,   r-   setup_logging)  s2   











r  c                 C   s`   | j dv r*t| j  t| dr,| jdkrttjj | jdkr.ttjj	 dS dS dS dS )z3Set the right event mode based on the args provided)r   r   r   r   r   rK   r   r    N)
r   r   Zset_commandhasattrrK   set_event_moder   ZEventLoggerModeZJSONZYAML)rn   r,   r,   r-   r  O  s   



r  c                    rX   )Nc                     s  z | i |W S  t y;   t  td W d    n1 s#w   Y  tdtjd t	  t
d Y d S  tjy } zdt|v rntj}tdrTtj}|j|jd}tj|j|jd tj|jtjd	 nDt # |j|d
}|jrtj}ntj}t|jdi | W d    n1 sw   Y  tj}tj|j|jd tj|jtjd	 t	  t  t
d W Y d }~d S d }~w tjy" } zKt  t|j W d    n1 sw   Y  tj|j|jd tjd|jtjd	 t|tj st	  t  t
|j! W Y d }~d S d }~w t"ys } zEt  td W d    n	1 s?w   Y  t	  tjtj#jtjd	 tjt$|dt|dd t  t
d W Y d }~d S d }~ww )NKeyboardInterruptzInterrupt received; exiting.r6   r   ZCERTIFICATE_VERIFY_FAILEDzca-certificates)rC   rL  )Zinfo_msgrM  )rC   r5   z{}z&Unhandled exception, please file a bugrj   rw   )r   Z
error_typer,   )%r  r   r|  r2  r5   r   r1   r2   r   Zclear_lock_file_if_presentr3   r   r1  rU   r   Z&SSL_VERIFICATION_ERROR_CA_CERTIFICATESZis_installedZ%SSL_VERIFICATION_ERROR_OPENSSL_CONFIGrK   rC   r   rj   rA   r   Z$LOG_CONNECTIVITY_ERROR_WITH_URL_TMPLZLOG_CONNECTIVITY_ERROR_TMPLrw   ZCONNECTIVITY_ERRORr)  rm   rk   r   ZLockHeldErrorZ	exit_code	ExceptionZUNEXPECTED_ERRORru   )r\   r]   rO  Ztmplrj   Zmsg_argsZmsg_tmplr8  funcr,   r-   rc   [  st   






z#main_error_handler.<locals>.wrapperr,   )r  rc   r,   r  r-   main_error_handlerZ  s   :r  c           
      C   s   | st j} t }| dd  }|s|  td t d |j|d}t| t	 }|j
}|j}tj||d |j}|jrAtjntj}t|||j ttd|   dd ttj D }	|	rmttd|	  |j||d	S )
Nr   z%Try 'ua --help' for more information.)r\   r  zExecuted with sys.argv: %rc                 S   s:   g | ]\}}|  tv s|d s|dkrd||qS )ZUA_FEATURESZUA_CONFIG_FILEz{}={})lowerr   
startswithrK   )r   kvr,   r,   r-   r     s    

zmain.<locals>.<listcomp>z*Executed with UA environment variables: %rr{   )r1   argvr   r0   r   r3   
parse_argsr  r   rH   r	  r
  r   Zconfigure_web_proxyr  r3  r2  DEBUGINFOr  r^  ra  r9   rf   environr  r   )
Zsys_argvr   Zcli_argumentsr\   rZ   r	  r
  r  r  Zua_environmentr,   r,   r-   main  s<   
r  __main__r<  )NN)zrj  rS   r   r2  rf   r  r   rb  r1   rd  r\  rL   rw  	functoolsr   typingr   r   r   r    Zuaclientr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   Zuaclient.cloudsr   r   Zuaclient.data_typesr   r   Zuaclient.defaultsr   r   r   r   r  r   Zuaclient.jobs.update_messagingr   r   r   rk  ZSTATUS_HEADER_TMPLr   r  r   r[  r]  Zget_event_loggerr   ArgumentParserr!   rd   rh   ro   rz   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rU   r   r   r   r   r   ZENABLE_FAILURE_UNATTACHEDr,  ru  ZNamedMessager-  r9  r  r;  rH   r:  rF  rJ  rQ  rW  ri  r   ro  rl  rp  r}  r~  rn  rm  r  r  r  r  rP   r3   r,   r,   r,   r-   <module>   s   4

J
('%"O"
P
&)
A9?Q
An





&>
'