
    Vh4%                         d dl mZmZmZ eZd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Zd	Zd
Zd Z G d de      Zy)    )absolute_importdivisionprint_functionu  
    name: grafana_annotations
    type: notification
    short_description: send ansible events as annotations on charts to grafana over http api.
    author: "Rémi REY (@rrey)"
    description:
      - This callback will report start, failed and stats events to Grafana as annotations (https://grafana.com)
    requirements:
      - whitelisting in configuration
    options:
      grafana_url:
        description: Grafana annotations api URL
        required: true
        env:
          - name: GRAFANA_URL
        ini:
          - section: callback_grafana_annotations
            key: grafana_url
        type: string
      validate_certs:
        description: validate the SSL certificate of the Grafana server. (For HTTPS url)
        env:
          - name: GRAFANA_VALIDATE_CERT
        ini:
          - section: callback_grafana_annotations
            key: validate_grafana_certs
          - section: callback_grafana_annotations
            key: validate_certs
        default: true
        type: bool
        aliases: [ validate_grafana_certs ]
      http_agent:
        description: The HTTP 'User-agent' value to set in HTTP requets.
        env:
          - name: HTTP_AGENT
        ini:
          - section: callback_grafana_annotations
            key: http_agent
        default: 'Ansible (grafana_annotations callback)'
        type: string
      grafana_api_key:
        description: Grafana API key, allowing to authenticate when posting on the HTTP API.
                     If not provided, grafana_login and grafana_password will
                     be required.
        env:
          - name: GRAFANA_API_KEY
        ini:
          - section: callback_grafana_annotations
            key: grafana_api_key
        type: string
      grafana_user:
        description: Grafana user used for authentication. Ignored if grafana_api_key is provided.
        env:
          - name: GRAFANA_USER
        ini:
          - section: callback_grafana_annotations
            key: grafana_user
        default: ansible
        type: string
      grafana_password:
        description: Grafana password used for authentication. Ignored if grafana_api_key is provided.
        env:
          - name: GRAFANA_PASSWORD
        ini:
          - section: callback_grafana_annotations
            key: grafana_password
        default: ansible
        type: string
      grafana_dashboard_id:
        description: The grafana dashboard id where the annotation shall be created.
        env:
          - name: GRAFANA_DASHBOARD_ID
        ini:
          - section: callback_grafana_annotations
            key: grafana_dashboard_id
        type: integer
      grafana_panel_ids:
        description: The grafana panel ids where the annotation shall be created.
                     Give a single integer or a comma-separated list of integers.
        env:
          - name: GRAFANA_PANEL_IDS
        ini:
          - section: callback_grafana_annotations
            key: grafana_panel_ids
        default: []
        type: list
        elements: integer
N)datetime)to_text)open_url)CallbackBasezDStarted playbook {playbook}

From '{hostname}'
By user '{username}'
zrPlaybook {playbook} Failure !

From '{hostname}'
By user '{username}'

'{task}' failed on {host}

debug: {result}
zuPlaybook {playbook}
Duration: {duration}
Status: {status}

From '{hostname}'
By user '{username}'

Result:
{summary}
c                 <    t        | j                  d            dz  S )Nz%si  )intstrftime)dts    z/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/grafana/plugins/callback/grafana_annotations.py	to_millisr      s    r{{4 !D((    c                   `     e Zd ZdZdZdZdZdZd fd	Zd fd	Z	d Z
d	 Zdd
Zd Zd Z xZS )CallbackModulez
    ansible grafana callback plugin
    ansible.cfg:
        callback_plugins   = <path_to_callback_plugins_folder>
        callback_whitelist = grafana_annotations
    and put the plugin in <path_to_callback_plugins_folder>
    g       @	aggregatez%community.grafana.grafana_annotationsTc                     t         t        |   |       ddi| _        d| _        t        j                         | _        t        j                         | _
        t        j                         | _        d| _        y )N)displayzContent-Typezapplication/jsonFr   )superr   __init__headersforce_basic_authsocketgethostnamehostnamegetpassgetuserusernamer   now
start_timeerrors)selfr   	__class__s     r   r   zCallbackModule.__init__   s\    nd,W,=&(:; %**,)",,.r   c                    t         t        |   |||       | j                  d      | _        | j                  d      | _        | j                  d      | _        | j                  d      | _        | j                  d      | _        | j                  d      | _	        | j                  d      | _
        | j                  d	      | _        | j                  rd
| j                  z  | j                  d<   nd| _        | j
                  "d| _        | j                  j!                  d       | j                  j#                  d| j
                  z         y )N)	task_keysvar_optionsdirectgrafana_api_keygrafana_urlvalidate_certs
http_agentgrafana_usergrafana_passwordgrafana_dashboard_idgrafana_panel_idsz	Bearer %sAuthorizationTzkGrafana URL was not provided. The Grafana URL can be provided using the `GRAFANA_URL` environment variable.zGrafana URL: %s)r   r   set_options
get_optionr)   r*   validate_grafana_certsr,   r-   r.   dashboard_id	panel_idsr   r   disabled_displaywarningdebug)r#   r&   r'   r(   r$   s       r   r2   zCallbackModule.set_options   s   nd/[ 	0 	
  $/@A??=9&*oo6F&G#//,7 OON; $0B C OO,BC)<=,7$:N:N,NDLL)$(D!# DMMM!!:
 	-0@0@@Ar   c                    |j                   | _        t        j                  | j                  | j                  | j
                        }t        | j                        |dd| j                  | j                  gd}| j                  |       y )N)playbookr   r   ansibleansible_event_starttimetexttags)	
_file_namer<   PLAYBOOK_START_TXTformatr   r   r   r!   _send_annotation)r#   r<   rA   datas       r   v2_playbook_on_startz#CallbackModule.v2_playbook_on_start   st     ++!((]]T]]T]] ) 
 doo. 5t}}dmmT

 	d#r   c           
      (   t        j                         }|| j                  z
  }i }|j                  j	                         D ]  }|j                  |      ||<    d}| j                  dk(  rd}t        j                  | j                  | j                  |j                         || j                  t        j                  |            }t        | j                        t        |      d|dd| j                  | j                  gd}| j!                  |       y )	NFAILEDr   OK)r<   r   durationstatusr   summaryTr=   ansible_report)r@   timeEndisRegionrA   rB   )r   r    r!   	processedkeys	summarizer"   PLAYBOOK_STATS_TXTrE   r<   r   total_secondsr   jsondumpsr   _send_annotations)	r#   statsend_timerL   summarize_stathostrM   rA   rG   s	            r   v2_playbook_on_statsz#CallbackModule.v2_playbook_on_stats   s    <<>doo-OO((* 	9D#(??4#8N4 	9 ;;!F!((]]]]++-]]JJ~. ) 
 doo. * 0$--O
 	t$r   c           
         t         j                  | j                  | j                  | j                  |j
                  |j                  j                  | j                  |j                              }|ry t        t        j                               |dd| j                  | j                  gd}| xj                  dz  c_        | j                  |       y )N)r<   r   r   taskr]   resultr=   ansible_event_failurer?      )PLAYBOOK_ERROR_TXTrE   r<   r   r   _task_hostname_dump_results_resultr   r   r    r"   rY   )r#   ra   ignore_errorskwargsrA   rG   s         r   v2_runner_on_failedz"CallbackModule.v2_runner_on_failed   s    !((]]]]]]""%%fnn5 ) 
 hlln- 7V

 	qt$r   c                     | j                   rt        | j                         |d<   | j                  r1| j                  D ]!  }t        |      |d<   | j                  |       # y | j                  |       y )NdashboardIdpanelId)r5   r   r6   rF   )r#   rG   panel_ids      r   rY   z CallbackModule._send_annotations  se    "%d&7&7"8D>> NN ,"%h-Y%%d+, !!$'r   c                 Z   	 t        | j                  t        j                  |      | j                  d| j
                  | j                  | j                  | j                  | j                  	       y # t        $ r1}| j                  j                  dt        |      z         Y d }~y d }~ww xY w)NPOST)rG   r   methodr+   url_usernameurl_passwordr,   r   z'Could not submit message to Grafana: %s)r   r*   rW   rX   r   r4   r-   r.   r,   r   	Exceptionr8   errorr   )r#   
annotationes      r   rF   zCallbackModule._send_annotation  s    	X  ZZ
+#::!..!22??!%!6!6
  	XMM IGTUJ VWW	Xs   A-A0 0	B*9'B%%B*)N)NNN)F)__name__
__module____qualname____doc__CALLBACK_VERSIONCALLBACK_TYPECALLBACK_NAMECALLBACK_NEEDS_WHITELISTr   r2   rH   r^   rl   rY   rF   __classcell__)r$   s   @r   r   r      sE     M;M#B8
$%:%&(Xr   r   )
__future__r   r   r   type__metaclass__DOCUMENTATIONrW   r   r   r   ansible.module_utils._textr   ansible.module_utils.urlsr   ansible.plugins.callbackr	   rD   rd   rU   r   r    r   r   <module>r      s`   " A @Wr     . . 1 	 
 )HX\ HXr   