
    VhW                     6   d dl mZmZmZ dZdZd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mZ 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 Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&e'd k(  r e&        yy)!    )absolute_importdivisionprint_functionu  
---
module: grafana_dashboard
author:
  - Thierry Sallé (@seuf)
version_added: "1.0.0"
short_description: Manage Grafana dashboards
description:
  - Create, update, delete, export Grafana dashboards via API.
options:
  org_id:
    description:
      - The Grafana organization ID where the dashboard will be imported / exported / deleted.
      - Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organization.
      - Mutually exclusive with C(org_name).
    default: 1
    type: int
  org_name:
    description:
      - The Grafana organization name where the dashboard will be imported / exported / deleted.
      - Not used when I(grafana_api_key) is set, because the grafana_api_key only belongs to one organization.
      - Mutually exclusive with C(org_id).
    type: str
  folder:
    description:
      - UID of the folder where the dashboard will be created or imported.
      - Required if C(parent_folder) is set.
    default: General
    version_added: "1.0.0"
    type: str
  parent_folder:
    description:
      - UID of the parent folder used to scope the search for the specified C(folder).
      - Available with subfolder feature of Grafana 11.
    version_added: "2.2.0"
    type: str
  state:
    description:
      - State of the dashboard.
    choices: [ absent, export, present ]
    default: present
    type: str
  slug:
    description:
      - Deprecated since Grafana 5. Use grafana dashboard uid instead.
      - slug of the dashboard. It's the friendly url name of the dashboard.
      - When C(state) is C(present), this parameter can override the slug in the meta section of the json file.
      - If you want to import a json dashboard exported directly from the interface (not from the api),
        you have to specify the slug parameter because there is no meta section in the exported json.
    type: str
  uid:
    version_added: "1.0.0"
    description:
      - Used to identify the dashboard when C(state) is C(export) or C(absent).
      - When C(state) is C(present), this can be used to set the UID during dashboard creation.
    type: str
  path:
    description:
      - The path to the json file containing the Grafana dashboard to import or export.
      - A http URL is also accepted (since 2.10).
      - Required if C(state) is C(export) or C(present).
    aliases: [ dashboard_url ]
    type: str
  overwrite:
    description:
      - Override existing dashboard when state is present.
    type: bool
    default: false
  dashboard_id:
    description:
      - Public Grafana.com dashboard id to import
    version_added: "1.0.0"
    type: str
  dashboard_revision:
    description:
      - Revision of the public grafana dashboard to import
    default: '1'
    version_added: "1.0.0"
    type: str
  commit_message:
    description:
      - Set a commit message for the version history.
      - Only used when C(state) is C(present).
    type: str
extends_documentation_fragment:
- community.grafana.basic_auth
- community.grafana.api_key
ac  
- name: Import Grafana dashboard foo
  community.grafana.grafana_dashboard:
    grafana_url: http://grafana.company.com
    grafana_api_key: "{{ grafana_api_key }}"
    state: present
    commit_message: Updated by ansible
    overwrite: true
    path: /path/to/dashboards/foo.json

- name: Import Grafana dashboard Zabbix
  community.grafana.grafana_dashboard:
    grafana_url: http://grafana.company.com
    grafana_api_key: "{{ grafana_api_key }}"
    folder: zabbix
    dashboard_id: 6098
    dashboard_revision: 1

- name: Import Grafana dashboard zabbix
  community.grafana.grafana_dashboard:
    grafana_url: http://grafana.company.com
    grafana_api_key: "{{ grafana_api_key }}"
    folder: public
    dashboard_url: https://grafana.com/api/dashboards/6098/revisions/1/download

- name: Import Grafana dashboard zabbix in a subfolder
  community.grafana.grafana_dashboard:
    grafana_url: http://grafana.company.com
    grafana_api_key: "{{ grafana_api_key }}"
    parent_folder: public
    folder: myteam
    dashboard_url: https://grafana.com/api/dashboards/6098/revisions/1/download

- name: Export dashboard
  community.grafana.grafana_dashboard:
    grafana_url: http://grafana.company.com
    grafana_user: "admin"
    grafana_password: "{{ grafana_password }}"
    org_id: 1
    state: export
    uid: "000000653"
    path: "/path/to/dashboards/000000653.json"
z
---
uid:
  description: uid or slug of the created / deleted / exported dashboard.
  returned: success
  type: str
  sample: 000000063
N)AnsibleModule)	fetch_url)	urlencode)	to_native)to_text)grafana_argument_spec	clean_urlc                       e Zd Zy)GrafanaAPIExceptionN__name__
__module____qualname__     w/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/grafana/plugins/modules/grafana_dashboard.pyr   r          r   r   c                       e Zd Zy)GrafanaMalformedJsonNr   r   r   r   r   r      r   r   r   c                       e Zd Zy)GrafanaExportExceptionNr   r   r   r   r   r      r   r   r   c                       e Zd Zy)GrafanaDeleteExceptionNr   r   r   r   r   r      r   r   r   c                     t        | d|z  |d      \  }}|d   dk7  rt        d|z        t        j                  t	        |j                                     }|D ]  }|d   |k(  s|d   c S  t        d	|z        )
Nz%s/api/user/orgsGETheadersmethodstatus   z*Unable to retrieve users organizations: %snameorgIdz-Current user isn't member of organization: %s)r   r   jsonloadsr
   read)modulegrafana_urlorg_namer    rinfoorganizationsorgs           r   grafana_organization_id_by_namer0      s    "[0'%GAt H~!"NQU"UVVJJwqvvx01M  v;("w<  7(B r   c                 d    t        | |d||d      \  }}|d   dk7  rt        d|d|      y )Nz/api/user/using/POSTr   r"   r#   z!Unable to switch to organization  : )r   r   )r)   r*   org_idr    r,   r-   s         r   grafana_switch_organizationr5      sI    "-v6	GAt H~!:@$G
 	
 r   c                     ddi}d|v r|d   rd|d   z  |d<   |S d| j                   d<   | j                   d   r#| j                   d   }t        | |d	   ||      |d
<   t        | |d	   |d
   |       |S )Nzcontent-typezapplication/json; charset=utf8grafana_api_keyz	Bearer %sAuthorizationTforce_basic_authr+   urlr4   )paramsr0   r5   )r)   datar    r+   s       r   grafana_headersr=      s    ?@GD T*;%<#.6G1H#H  N -1()==$}}Z0H<UXwDN 	$FDKhQNr   c                 ^   d }t        | d|z  |d      \  }}|d   dk(  rR	 t        j                  t        |j	                                     }|d   d   j                  d      d	   }t        |      S t        d|z        # t        $ r t        d
      t        $ r}t        |      d }~ww xY w)Nz%s/api/frontend/settingsr   r   r"   r#   	buildInfoversion.r   z*Unable to decode version string to Unicodez!Unable to get grafana version: %s)
r   r&   r'   r
   r(   splitUnicodeErrorr   	Exceptionint)r)   r*   r    grafana_versionr,   r-   settingses           r   get_grafana_versionrI      s    O*[8'RWGAt H~	)zz'!&&("34H&{3I>DDSI!LO  ""E"LMM  	T%&RSS 	)%a((	)s   AB   B,B''B,c                 @   |dk(  ry	 d|z  }|r|d|}t        | ||d      \  }}|d   dk7  rt        d	||d   fz        t        j                  |j	                               }|D ]  }	||	d
   |	d   fv sd|	d   fc S  	 y# t
        $ r}
t        |
      d }
~
ww xY w)NGeneral)Tr   z%s/api/foldersz?parentUid=r   r   r"   r#   z6Unable to query Grafana API for folders (name: %s): %dtitleuidTid)Fr   )r   r   r&   r'   r(   rD   )r)   r*   folder_nameparent_folderr    r:   r,   r-   foldersfolderrH   s              r   grafana_folder_existsrS      s    i%,'*M:CFCG4>S %HX/0 
 **QVVX& 	*Fvgu>>VD\))	*   %!!$$%s$   A/B 8B B 	BBBc                 J   d}i }t        | ||      }|dk\  r|d|}n|d|}t        | ||d      \  }}	|	d   dk(  r*d	}	 t        j                  |j	                               }||fS |	d   d
k(  rd}||fS t        d|d|	      # t
        $ r}
t        |
      d }
~
ww xY w)NF   /api/dashboards/uid//api/dashboards/db/r   r   r"   r#   Ti  zUnable to get dashboard r3   )rI   r   r&   r'   r(   rD   r   )r)   r*   rM   r    dashboard_exists	dashboardrF   urir,   r-   rH   s              r   grafana_dashboard_existsr[     s    I)&+wGO!,7=+6<WUCGAtH~	)

1668,I Y&& 
h3	  Y&& "sD"QRR  	)%a((	)s   #B	 		B"BB"c                 H   |dt        ||dd      }t        | ||d      \  }}|d   dk(  rH	 t        j                  |j	                               }|D ]  }	|	d   |k(  st        | ||	d	   |      c S  	 yt        d
|d|      # t        $ r}
t        |
      d }
~
ww xY w)Nz/api/search?zdash-db)	folderIdsquerytyper   r   r"   r#   rL   rM   zUnable to search dashboard r3   )FN)r   r   r&   r'   r(   r[   rD   r   )r)   r*   	folder_idrL   r    rZ   r,   r-   
dashboardsdrH   s              r   grafana_dashboard_searchrc   ,  s     		E9MNC WUCGAtH~	)AFFH-J W:&3QuXw   "%QU"VWW  	)%a((	)s#   0B !B 4B 	B!BB!c                     d| d   v r| d   d= d|d   v r|d   d= d|v r|d= d| v r| d= d|vrd|d<   d|d   v r|d   d= d| d   v r| d   d= | |k(  ryy)	Nr@   rY   metafolderIdr   rN   FTr   )payloadrY   s     r   is_grafana_dashboard_changedrh   E  s    GK((K +Ik**k"9- fFO " !	* y%%k"4(w{##K &)r   c                    i }|j                  d      rd|d   d|d   d|d<   |d   j                  d      rRt        | |d         \  }}|d   d	k7  rt        d
|d   d|      t	        j
                  |j                               }n0	 t        |d   dd      5 }t	        j                  |      }d d d        d|vrd|i}t        | |      }t        | |d   |      }|dk  rA|j                  d      xs! |j                  di       j                  d      }	|	s[t        d      |j                  d      xs! |j                  di       j                  d      }	|j                  d      r|d   |d   d<   i }
d}|d   r|dk  r| j                  dd       |dk\  r5t        | |d   |d   |d   |      \  }}|du rt        d|d   z        ||d<   |	rt!        | |d   |	|       \  }}nt#        | |d   |d   d!   |       \  }}|du rt%        ||      }|r| j&                  r| j)                  |	ddd"|d   d!   z  #       d$|v r
|d$   rd|d$<   d%|v r|d%   r|d%   |d&<   t        | d'|d   z  t	        j*                  |      |d()      \  }}|d   d	k(  rH|dk\  r)	 t	        j
                  |j                               }|d   }	|	|
d<   d*|d   d!   z  |
d+<   d|
d,<   |
S t	        j
                  |d-         }t        d.|	|d&   |d   fz        |	|
d<   d/|d   d!   z  |
d+<   d|
d,<   |
S | j&                  r| j)                  ddd0|d   d!   z  1       d2|d   v r|d   d2= t        | d'|d   z  t	        j*                  |      |d()      \  }}|d   d	k(  rHd3|d   d!   z  |
d+<   d|
d,<   |dk\  r)	 t	        j
                  |j                               }|d   }	|	|
d<   |
S t        d4|d   d!   d|d   d5|d6|d7	      # 1 sw Y   GxY w# t        $ r}t        dt        |      z        d }~ww xY w# t        $ r}t        |      d }~ww xY w# t        $ r}t        |      d }~ww xY w)8Ndashboard_idz#https://grafana.com/api/dashboards/z/revisions/dashboard_revisionz	/downloadpathhttpr"   r#   z.Unable to download grafana dashboard from url r3   r,   utf-8encodingzCan't load json file %srY   r:   rU   slugre   z.No slug found in JSON. Needed with Grafana < 5rM   FrP      Tz/Subfolder API is available starting Grafana v11failedmsgrR   z%Dashboard folder '%s' does not exist.rf   r    rL   zDashboard %s will be updatedrM   rt   changedru   	overwritecommit_messagemessagez%s/api/dashboards/dbr2   )r<   r    r!   zDashboard %s updatedru   rx   bodyz1Unable to update the dashboard %s : %s (HTTP: %d)zDashboard %s unchanged.zDashboard %s will be created)rt   rx   ru   rN   zDashboard %s createdz#Unable to create the new dashboard z - z. (headers : ))get
startswithr   r   r&   r'   r(   openloadrD   r	   r=   rI   r   	fail_jsonrS   r[   rc   rh   
check_mode	exit_jsondumps)r)   r<   rg   r,   r-   	json_filerH   r    rF   rM   resultfolder_existsr`   rX   rY   grafana_dashboard_changedr|   s                    r   grafana_create_dashboardr   a  s   Gxx %&
V F|v&FDL14>S %<'  **QVVX&	Pd6lC': /i))I./ '!( fd+G)&$u+wGOhhvE'++fb"9"="=f"E&'WXXhhuoH["!=!A!A%!H88E?*.u+GK 'F MO2!5N 	 	
 !#8DKho1F$
 y E!%7$x.H  (
 &>DKg'
#) '?KK )'
#) 4$@)$T!$      69Mg9VV	 !  d"tK'8'+$4'D1A,B%)*:%;	"&e4ZZ(GAt H~$"a'5$(JJqvvx$8	'. !$u 69Mg9V Vu$(y!^ M[ zz$v,/)GDOT(^<=   F5M58LW8UUF5M %F9H ME 2W[5I'5RR   7;''$T*"T%[0G$
4 >S 2W[5I'5RRF5M $F9!#1 $

1668 4I#E*C  F5M M &;'0$x.$Q I/ / 	P%&?)A,&NOO	Ph % 51!445T ! 1-a001s`   P O94P (P. )(Q
 9P>P 	P+P&&P+.	Q7QQ
	Q#QQ#c                 .   t        | |      }t        | |d   |      }|dk  r"|j                  d      r|d   }n-t        d      |j                  d      r|d   }nt	        d      t        | |d   ||      \  }}i }|du r| j                  r| j                  |d	dd
|z         |dk  rt        | |d   d||d      \  }}	nt        | |d   d||d      \  }}	|	d   dk(  rd|z  |d<   d|d<   ||d<   |S t        d|d|	      d|z  d	|d}|S )Nr:   rU   rq   *No slug parameter. Needed with grafana < 5rM   zNo uid specified %srv   TFzDashboard %s will be deletedrw   rW   DELETEr   rV   r"   r#   zDashboard %s deletedru   rx   zUnable to update the dashboard r3   Dashboard %s does not exist.)ru   rx   rM   )
r=   rI   r~   r   r   r[   r   r   r   r   )
r)   r<   r    rF   rM   rX   rY   r   r,   r-   s
             r   grafana_delete_dashboardr     s   fd+G)&$u+wGO88Fv,C&'STT88E?u+C()>?? #;US'#i F42S8	   Q-1%[#>	GAt  .25k3?	GAt >S 2S8F5M $F9F5M M &<?F  2C7
 Mr   c           
      t   t        | |      }t        | |d   |      }|dk  r"|j                  d      r|d   }n-t        d      |j                  d      r|d   }nt	        d      t        | |d   ||      \  }}|du r|| j                  r| j                  |d	dd
|d|d          	 t        |d   dd      5 }|j                  t        j                  |d             d d d        d
|d|d   |dd}	|	S d|z  |d	d}	|	S # 1 sw Y   %xY w# t        $ r}t	        dt        |      z        d }~ww xY w)Nr:   rU   rq   r   rM   zNo uid specifiedrv   TFz
Dashboard z will be exported to rl   rw   wrn   ro      )indentzCan't write json file : %sz exported to )ru   rM   rx   r   )r=   rI   r~   r   r   r[   r   r   r   writer&   r   rD   r	   )
r)   r<   r    rF   rM   rX   rY   frH   r   s
             r   grafana_export_dashboardr   @  so   fd+G)&$u+wGO88Fv,C&'STT88E?u+C();<< #;US'#i 4=@$v,O	  	Vd6lC': 9a

9Q789
 58fF
 M 2C7
 M!9 9 	V()E	RS)TUU	Vs0   *D ;'D"D DD 	D7D22D7c                  j   t               } | j                  t        g dd      t        dd      t        d      t        dd	
      t        d      t        d      t        d      t        dgd      t        d      t        dd
      t        dd
      t        d             t        | ddddgggg dgddgddgddgddgg      }t	        |j
                  d         |j
                  d<   	 |j
                  d   dk(  rt        ||j
                        }n?|j
                  d   dk(  rt        ||j
                        }nt        ||j
                        } |j                  d%d$di| y # t        $ r)}|j                  dd t        |      z  !       Y d }~y d }~wt        $ r)}|j                  dd t        |      z  !       Y d }~y d }~wt        $ r)}|j                  dd"t        |      z  !       Y d }~y d }~wt        $ r)}|j                  dd#t        |      z  !       Y d }~y d }~ww xY w)&N)presentabsentexportr   )choicesdefault   rE   )r   r_   str)r_   rK   )r_   r   dashboard_url)aliasesr_   1boolF)stater4   r+   rR   rP   rM   rq   rl   rj   rk   ry   rz   Tr   r   rl   )url_usernameurl_passwordr4   r   r7   rM   rq   rj   r4   r+   )argument_specsupports_check_moderequired_ifrequired_togethermutually_exclusiver:   r   z
error : %srs   z#error : Can't delete dashboard : %sz#error : Can't export dashboard : %srt   r   )r   updatedictr   r   r;   r   r   r   r   r   r	   r   r   r   r   )r   r)   r   rH   s       r   mainr   q  s)   )+M:INAE*5!	2&eu?+%8u%UC8FE2'   # h)
 FF./FO^$z"	
F %V]]5%9:FMM%==!Y.-ffmmDF]]7#x/-ffmmDF-ffmmDF$ F,E,V,
%  ,1*EF ,1*EF! BYq\Q 	 	
 	! BYq\Q 	 	
 		s=   3A(E0 0	H29FH2)GH2G==H2	H--H2__main__)(
__future__r   r   r   DOCUMENTATIONEXAMPLESRETURNr&   ansible.module_utils.basicr   ansible.module_utils.urlsr   +ansible.module_utils.six.moves.urllib.parser   ansible.module_utils._textr	   r
   ?ansible_collections.community.grafana.plugins.module_utils.baser   r   r_   __metaclass__rD   r   r   r   r   r0   r5   r=   rI   rS   r[   rc   rh   r   r   r   r   r   r   r   r   <module>r      s    A @Wr*X
  4 / A 0 .
 	) 		9 		Y 		Y 	 

  &:'428[|>B.b;| zF r   