o
    id                      @   sJ   d dl Z d dlZd dlZd dlmZ d	ddZdd ZG dd deZdS )
    N)Clusterc                 C   s   | sg S dd |  dD S )zParse comma separated string.c                 S   s   g | ]}|  qS  )strip).0stringr   r   =/usr/lib/python3/dist-packages/sos/collector/clusters/juju.py
<listcomp>   s    z(_parse_option_string.<locals>.<listcomp>,)split)stringsr   r   r   _parse_option_string   s   r   c                 C   s   G dd d}|| S )aR  Helper function to get Index.

    The reason why we need Index defined in function is because currently
    the collector.__init__ will load all the classes in this module
    and also Index. This will cause bug because it think Index is
    Cluster type. Also We don't want to provide a customized
    filter to remove Index class.
    c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )z_get_index.<locals>.IndexzIndex structure to help parse juju status output.

        Attributes apps, units and machines are dict which key
        is the app/unit/machine name
        and the value is list of targets which format are
        {model_name}:{machine_id}.
        c                 S   s(   || _ i | _i | _i | _td| _d S )Nsos)
model_nameappsunitsmachineslogging	getLoggerui_log)selfr   r   r   r   __init__,   s
   z"_get_index.<locals>.Index.__init__c           
      S   s   |d   D ]7\}}g }|di }|  D ]!\}}|d }| j d| }	|	g| j|< |	g| j|< ||	 q|| j|< qdS )zAdds principal units to index.applicationsr   machine:N)itemsgetr   r   r   appendr   )
r   juju_statusappapp_infonodesr   unit	unit_infor   noder   r   r   add_principals3   s   z(_get_index.<locals>.Index.add_principalsc                 S   s   |d   D ]s\}}|dg }|D ]f}| j|s%| jd| d q| j| | j|  d|d | vrC| jd| d q|d | d }|  D ](\}}| j d|d  }	|d	i   D ]\}
}|
|d
 rv|	g| j|
< qeqOqqdS )zAdd subordinates to index.

            Since subordinates does not have units they need to be
            manually added.
            r   zsubordinate-tozPrincipal charm z is missingr   z is missing unitsr   r   subordinates/N)	r   r   r   r   warningextendr   
startswithr   )r   r   r   r   subordinate_toparentr   r!   r"   r#   sub_key	sub_valuer   r   r   add_subordinatesA   s:   


z*_get_index.<locals>.Index.add_subordinatesc                 S   s2   |d   D ]}| j d| }|g| j|< qdS )zAdd machines to index.

            If model does not have any applications it needs to be
            manually added.
            r   r   N)keysr   r   )r   r   r   r#   r   r   r   add_machinesb   s   z&_get_index.<locals>.Index.add_machinesN)__name__
__module____qualname____doc__r   r$   r.   r0   r   r   r   r   Index#   s    !r5   r   )r   r5   r   r   r   
_get_index   s   
Ir6   c                   @   sX   e Zd ZdZd ZdZg dZdd Zdd Zdd	 Z	d
d Z
dd Zdd Zdd ZdS )jujua!  
    The juju cluster profile is intended to be used on juju managed clouds.
    It"s assumed that `juju` is installed on the machine where `sos` is called,
    and that the juju user has superuser privilege to the current controller.

    By default, the sos reports will be collected from all the applications in
    the current model. If necessary, you can filter the nodes by models /
    applications / units / machines with cluster options.

    Example:

    sos collect --cluster-type juju -c "juju.models=sos" -c "juju.apps=a,b,c"

    zJuju Managed Clouds))r    z1Filter node list by apps (comma separated regex).)r   r8   z3Filter node list by units (comma separated string).)modelsr8   z4Filter node list by models (comma separated string).)r   r8   z6Filter node list by machines (comma separated string).c                 C   s   t dd|dt jS )z#Remove leading characters before {.z(^[^{]*)(.*)z\2r   )resub	MULTILINE)r   outputr   r   r   _cleanup_juju_output   s   zjuju._cleanup_juju_outputc                 C   s6   |  |}t|d}|| || || |S )zParse juju status output and return target dict.

        Here are couple helper functions to parse the juju principals units,
        subordinate units and machines.
        )r   )_execute_juju_statusr6   r$   r.   r0   )r   r   r   indexr   r   r   _get_model_info   s   




zjuju._get_model_infoc                 C   s   |rd| nd}d}| j  d| d| }| |}|d dks-td| d	|d  | |d
 }d }zt|}W |S  tjyM   td| w )Nz-m r8   z--format jsonz status  statusr   'z' returned error: r=   z-Juju output is not valid json format.Output: )cmdexec_primary_cmd	Exceptionr>   jsonloadsJSONDecodeError)r   r   model_optionformat_option
status_cmdresjuju_json_outputr   r   r   r   r?      s$   
zjuju._execute_juju_statusc                 C   sF   t  }|D ]}t|| D ]\}}t||r||pg  qq|S )zFilter with regex match.)setgetattrr   r:   matchupdater   keypatterns
model_infor    patternparamvaluer   r   r   _filter_by_pattern   s   zjuju._filter_by_patternc                 C   sB   t  }|D ]}t|| D ]\}}||kr||pg  qq|S )zFilter with fixed match.)rP   rQ   r   rS   rT   r   r   r   _filter_by_fixed   s   zjuju._filter_by_fixedc                 C   s   dS )z'Dynamically change transport to 'juju'.r7   r   )r   r   r   r   set_transport_type   s   zjuju.set_transport_typec                 C   s   t | d}t | d}t | d}t | d}|||d}t| s,|s,g S |s1dg}t }|D ](}| |}| D ]\}	}
|	dkrQ| |	|
|}n| |	|
|}|	| qAq6t
|S )z+Get the machine numbers from `juju status`.r9   r   r   r   )r   r   r   r8   )r   
get_optionanyvaluesrP   rA   r   r[   r\   rS   list)r   r9   r   r   r   filtersr    modelrW   rU   resource_nodesr   r   r   	get_nodes   s&   
zjuju.get_nodesN)r1   r2   r3   r4   rE   cluster_nameoption_listr>   rA   r?   r[   r\   r]   rf   r   r   r   r   r7   o   s    		r7   )N)r   rH   r:   sos.collector.clustersr   r   r6   r7   r   r   r   r   <module>   s   

V