PSGrafana.psm1

function Get-GrafanaAlert {
    <#
    .SYNOPSIS
    Query Grafana API for alert information
     
    .PARAMETER DashboardId
    The ID of the dashboard to query
     
    .PARAMETER DashboardName
    The friendly name of the dashboard to query
     
    .PARAMETER DashboardTag
    Search for alerts belong to a dashboard with a specific tag
     
    .PARAMETER AlertName
    Query for all alerts matching the alert name
     
    .PARAMETER State
    Query for all alerts in the state of 'ALL','no_data','paused', 'alerting','ok','pending'
     
    .EXAMPLE
    Get-GrafanaAlert
 
    .EXAMPLE
    Get-GranaAlert -DashboardId 1
 
    .EXAMPLE
    Get-GrafanaAlert -DashboardName "PeterRabbit"
 
    .EXAMPLE
    Get-GrafanaAlert -DashboardTag 'prod'
 
    .EXAMPLE
    Get-GrafanaAlert -AlertName 'Perrywinkle'
 
    .EXAMPLE State
    Get-GrafanaAlert -State 'paused'
 
    #>

    
    [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaAlert")]
    Param(
        
        [Parameter()]
        [Int[]]
        $DashboardId,

        [Parameter()]
        [String]
        $DashboardName,

        [Parameter()]
        [String[]]
        $DashboardTag,

        [Parameter()]
        [Alias('Query')]
        [String]
        $AlertName,

        [Parameter()]
        [String[]]
        [ValidateSet('ALL','no_data','paused', 'alerting','ok','pending')]
        $State
    )

    begin { $null = Get-GrafanaConfig } 

    process { 
        
        $irmParams = @{
            headers = @{ Authorization = "Bearer $($Configuration.apikey)"}
            Method      = "GET"
            ContentType = "application/json"
        }

        If($PSBoundParameters.Count -eq 0){

            $irmParams.Add("Uri","$($configuration.GrafanaUri)/alerts")
        }

        Else {

            Switch($PSBoundParameters.Keys){ 

                "DashboardName" {

                    $irmParams.Add("Uri","$($configuration.GrafanaUri)/alerts?dashboardQuery=$Dashboardname")

                }

                "DashboardId" { 
                    
                    $url = "$($configuration.GrafanaUri)/alerts?"
                    foreach ($id in $DashboardId) {
                        $url += "dashboardId={0}&" -f $id
                    }
                    $irmParams.Add("Uri","$($url -replace ".$")")
                
                }

                "DashboardTag" {

                    $url = "$($configuration.GrafanaUri)/alerts?"
                    foreach ($id in $DashboardTag) {
                        $url += "dashboardTag={0}&" -f $id
                    }
                    $irmParams.Add("Uri","$($url -replace ".$")")

                }

                "State" {
                    
                    $url = "$($configuration.GrafanaUri)/alerts?"
                    foreach ($id in $State) {
                        $url += "state={0}&" -f $id
                    }
                    $irmParams.Add("Uri","$($url -replace ".$")")

                }

                "Alertname" { 

                    $irmParams.Add("Uri","$($configuration.GrafanaUri)/alerts?query=$AlertName")

                }
                
            }#switch
        
        }#else

        $irmParams['Uri']
        Invoke-RestMethod @irmParams

    }#process

}
function Get-GrafanaApiKey {
    <#
        .SYNOPSIS
        Retrieve a list of API keys created in Grafana
 
        .EXAMPLE
        Get-GrafanaApiKey
    #>

    [cmdletBinding(HelpUri="ttps://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaApiKey")]
    Param()
    
    begin { $null = Get-GrafanaConfig }

    process {
        
        $header = @{ Authorization = "Bearer $($Configuration.apikey)"}

        $irmParams = @{
            Method = 'GET'
            Uri = "$($Configuration.GrafanaUri)/auth/keys"
            Headers = $header
            ContentType = "application/json"

        }

        Invoke-RestMethod @irmParams
    }
}
function Get-GrafanaConfig {
    <#
        .SYNOPSIS
        Reads the Grafana.json file and returns an object
         
        .PARAMETER ConfigurationFile
        The path to the configuration json. Defaults to Config\Grafana.json
         
        .EXAMPLE
        Get-GrafanaConfig
         
        .EXAMPLE
        Get-GrafanaConfig -ConfigurationFile C:\Configs\Grafana.json
         
    #>

    [CmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaConfig")]
    Param(
        [Parameter(Position=0)]
        [String]

        $ConfigurationFile = "$PSScriptRoot\Config\Grafana.json"

    )

    begin {}

    process {
        
        $Global:Configuration = Get-Content $ConfigurationFile | ConvertFrom-Json 

        $Configuration
    
    }

    end {}

}
function Get-GrafanaDashboard {
    <#
        .SYNOPSIS
        Returns an object with details about a Grafana dashboard
         
        .PARAMETER Name
        Search the Grafana instance for dashboards by friendly name
         
        .PARAMETER Uuid
        Search the Grafana instance for dashboards by UID
         
        .PARAMETER Tag
        Search the Grafana instance for dashboards by Tag
         
        .PARAMETER IncludeMetadata
        Include extra metadata about the dashboard. Excluded by default.
         
        .EXAMPLE
        Get-GrafanaDashboard -Name 'Prod - FileServer'
         
        .EXAMPLE
        Get-GrafanaDashboard -Uuid O0E3f5t
         
        .EXAMPLE
        Get-GrafanaDashboard -Name 'Smiley' -IncudeMetadata
     
    #>

    [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaDashboard")]
    Param(

        [Parameter(Position=0,ParameterSetName='Name')]
        [String]
        $Name,

        [Parameter(Position=0,ParameterSetName='Uuid')]
        [String]
        $Uuid,

        [Parameter(Position=0,ParameterSetName='Tag')]
        [String]
        $Tag,

        [Parameter()]
        [Switch]
        $IncludeMetadata
    )

    begin { $null = Get-GrafanaConfig }

    process {

        $header = @{ Authorization = "Bearer $($Configuration.apikey)"}

        Switch($PSCmdlet.ParameterSetName){

            'Name' {
                
                $irmParams = @{
            
                    Method      = "GET"
                    Uri         = "$($configuration.GrafanaUri)/search?query=$Name"
                    Headers     = $header
                    ContentType = "application/json"

                }

                $result = Invoke-WebRequest @irmParams

                $result.Content | ConvertFrom-Json
            
            }

            'Uuid' {
                
                $irmParams = @{
            
                    Method      = "GET"
                    Uri         = "$($configuration.GrafanaUri)/dashboards/uid/$uuid" 
                    Headers     = $header
                    ContentType = "application/json"
    
                }

                $result = Invoke-RestMethod @irmParams
                
                If($IncludeMetadata){
            
                    $result | Format-List
        
                }
        
                Else { 
        
                    $result.dashboard
                }
            
            }

            'Tag' {
                
                $irmParams = @{
            
                    Method      = "GET"
                    Uri         =  "$($configuration.GrafanaUri)/search?tag=$Tag" 
                    Headers     = $header
                    ContentType = "application/json"
    
                }

                $result = Invoke-WebRequest @irmParams
                
                $result.Content | ConvertFrom-Json
            
            }
        
        }#switch
                
    }#process

}#function
function Get-GrafanaDatasource {
    <#
    .SYNOPSIS
    Fetch information about Grafana datasources via the API
     
    .PARAMETER All
    Returns all datasources in your Grafana Instance
     
    .PARAMETER DatasourceId
    The ID of the datasource for which to search
     
    .PARAMETER DatasourceName
    The friendly name of the datasource for which to search
     
    .EXAMPLE
    Get-GrafanaDatasource -All
 
    .EXAMPLE
    Get-GrafanaDatasource -DatasourceId 4
 
    .EXAMPLE
    Get-GrafanaDatasource -Datasourcename ElasticPuppies
     
    .NOTES
     
    #>

    
    [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaDatasource")]
    Param(
        [Parameter()]
        [Switch]
        $All,

        [Parameter()]
        [Int]
        $DatasourceId,

        [Parameter()]
        [String]
        $DatasourceName

    )

    begin { $null = Get-GrafanaConfig }

    process {

        $header = @{ Authorization = "Bearer $($Configuration.apikey)"}

        If($All){

            $irmParams = @{
            
                Method      = "GET"
                Uri         = "$($configuration.GrafanaUri)/datasources" 
                Headers     = $header
                ContentType = "application/json"

            }

            $result = Invoke-RestMethod @irmParams

            $result
        }

        Switch($PSBoundParameters.Keys){

            'DatasourceId' {
                $irmParams = @{
            
                    Method      = "GET"
                    Uri         = "$($configuration.GrafanaUri)/datasources/$DatasourceId" 
                    Headers     = $header
                    ContentType = "application/json"
    
                }
    
                $result = Invoke-RestMethod @irmParams
    
                $result
            }

            'DatasourceName' {
                $irmParams = @{
            
                    Method      = "GET"
                    Uri         = "$($configuration.GrafanaUri)/datasources/name/$DatasourceName" 
                    Headers     = $header
                    ContentType = "application/json"
    
                }
    
                $result = Invoke-RestMethod @irmParams
    
                $result

            }
        }

    }
}
function Get-GrafanaServerHealth {
    <#
         
        .SYNOPSIS
        Returns Grafana server health info
 
        .EXAMPLE
 
        Get-GrafanaServerhealth
 
    #>


    [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaServerHealth")]
    Param()
    
    begin { $null = Get-GrafanaConfig}

    process {
        
         Invoke-RestMethod -Uri "$($Configuration.GrafanaUri)/health"
    
    }

}
function New-GrafanaApiKey {
    <#
        .SYNOPSIS
        Creates a new API key in Grafana
         
        .PARAMETER Name
        The friendly name of the API key
         
        .PARAMETER Role
        The access level for the key. Available options are Admin,Editor, and Viewer
         
        .EXAMPLE
        New-GrafanaApiKey -Name RickyBobby -Role Admin
 
        .EXAMPLE
        New-GrafanaApiKey -Name Alice -Role Editor
 
        .NOTES
        The generated API key is only displayed at runtime. If you need to retain it for any reason, be sure to it somewhere safe.
        It is highly recommended you run this command saved to a variable such as $ApiKey = New-GrafanaApiKey -Name ElmerFudd -Role Viewer.
        This way you can access the properties Name and Key within the variable. E.g. $ApiKey.name, or $ApiKey.key.
    #>

    [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/New-GrafanaApiKey")]
    Param(
        
        [Parameter(Mandatory,Position=0)]
        [String]
        $Name,

        [Parameter(Mandatory,Position=1)]
        [ValidateSet('Admin','Viewer','Editor')]
        [String]
        $Role

    )

    begin { 
        
        $null = Get-GrafanaConfig
        
    }

    process {
        
        $header = @{ Authorization = "Bearer $($Configuration.apikey)"}
        $body = @{name = $Name; role = $Role} | ConvertTo-Json

        $irmParams = @{
            Method = 'POST'
            Uri = "$($Configuration.GrafanaUri)/auth/keys"
            Body = "$body"
            Headers = $header
            ContentType = "application/json"

        }
        Write-Warning -Message "You'll only see the API key generated here one time. There is no method to retrieve/generate it."
        Invoke-RestMethod @irmParams

    }

}
function New-GrafanaSnapshot {
    <#
        .SYNOPSIS
        Take a snapshot of a dashboard in Grafana
 
        .PARAMETER DashboardTitle
        Title of the dashboard you wish to snapshot
 
        .PARAMETER SnapshotName
        Name of the snapshot you are creating
 
        .PARAMETER Expires
        Time (in seconds) the snapshot stays alive. Set to 0 to never expire.
     
        .EXAMPLE
        New-GrafanaSnapshot -DashboardTitle WebHosts -SnapshotName WebSnap -Expires 0
         
        Create a new snapshot of WebHosts with the name WebSnap that never expires
    #>


    [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/New-GrafanaSnapshot")]
    Param(

        [Parameter(Mandatory,Position=0)]
        [String]
        $DashboardTitle,

        [Parameter(Mandatory,Position=1)]
        [String]
        $SnapshotName,

        [Parameter(Position=0)]
        [Int]
        $Expires = 0
    )

    begin { $null = Get-GrafanaConfig}
    
    process {
        
        
        $irmParams = @{
            
            headers = @{ Authorization = "Bearer $($Configuration.apikey)"}
            body= @{
            
                dashboard = [ordered]@{
                editable     = $False
                hideControls = $True
                nav          = @(@{enable=$False
                                type = 'timepicker'})
                rows         = @(@{})
                style        = "dark"
                tags         = @()
                templating   = @{list = @()}
                time         = @{}
                timezone    = "browser"
                title        = "$DashboardTitle"
                version      = 5
                }
                expires = $Expires
                name = "$SnapshotName"
            
            } | ConvertTo-Json -Depth 4
            Method      = "POST"
            Uri         = "$($configuration.GrafanaUri)/snapshots"
            ContentType = "application/json"


        }

        Invoke-RestMethod @irmParams

    }
}
function New-GraphanaGraphPanel {

    [cmdletBinding()]
    Param(
        [Parameter(Mandatory,Position=0)]
        [String]
        $Title,

        [Parameter(Mandatory,Position=1)]
        [String]
        $Description,

        [Parameter(Mandatory,Position=2)]
        [String]
        $Datasource,

        [Parameter(Mandatory,Position=3)]
        [String]
        [ValidateSet('graph','singlestat','gauge','table','text','heatmap','alert list','dashboard list','plugin list')]
        $Type,
        
        [Parameter()]
        [Switch]
        $Transparent,

        [Parameter()]
        [Array]
        $valueMappings,

        [Parameter()]
        [Switch]
        $showThresholdLabels,

        [Parameter()]
        [Switch]
        $showThresholdMarkers,

        [Parameter()]
        [Int]
        $minValue,

        [Parameter()]
        [int]
        $thresholds_Index,

        [Parameter()]
        [string]
        $threshold_HexColor,

        [Parameter()]
        [int]
        $threshold_Value

        

    )

    begin {}

    process {
        $panelHash = @{
            
        }

    }

    end {}

}
function Remove-GrafanaApiKey {
    <#
    .SYNOPSIS
    Deletes an API key from your Grafana Instance
     
    .PARAMETER ApiId
    The ID of the API Key you wish to delete
     
    .EXAMPLE
    Remove-GrafanaApiKey -ApiId 6
 
    #>

    
    [cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High",HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Remove-GrafanaApiKey")]
    Param(

    [Parameter(Mandatory,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Int]
    $ApiId

    )

    begin { $Null = Get-GrafanaConfig }

    process {

        If($PSCmdlet.ShouldProcess("ID: $ApiId","DELETE")){

            $header = @{ Authorization = "Bearer $($Configuration.apikey)"}
            
            $irmParams = @{

                Method = "DELETE"
                Uri = "$($Configuration.GrafanaUri)/auth/keys/$ApiId"
                Headers = $header
                ContentType = "application/json"
            }

            Invoke-RestMethod @irmParams

        }
    }
}
function Remove-GrafanaDatasource {
    <#
        .SYNOPSIS
        Removes the specified Grafana datasource
         
        .PARAMETER DatasourceId
        The ID of the datasource you wish to remove
         
        .PARAMETER DatasourceName
        The friendly name of the datasouce you wish to remove
         
        .EXAMPLE
        Remove-GrafanaDashboard -DatasourceId 3
         
        .EXAMPLE
        Remove-GrafanaDashboard -DatasourceName 'ElasticPuppies'
    #>

    [cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High",HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Remove-GrafanaDatasource")]
    param(
        
        [Parameter()]
        [Int]
        $DatasourceId,

        [Parameter()]
        [String]
        $DatasourceName
    )

    begin { $null = Get-GrafanaConfig }

    process {

        $header = @{ Authorization = "Bearer $($Configuration.apikey)"}

        Switch($PSBoundParameters.Keys){
                
            'DatasourceId' {    
                
                    $irmParams = @{
                    
                    Method      = "DELETE"
                    Uri         = "$($configuration.GrafanaUri)/datasources/$DatasourceId" 
                    Headers     = $header
                    ContentType = "application/json"

                }

                If($PSCmdlet.ShouldProcess("DELETE","Datasource ID:$DatasourceId")){
                    
                    Invoke-RestMethod @irmParams
                
                }
            }

            'DatasourceName' {    
                
                $irmParams = @{
                    
                    Method      = "DELETE"
                    Uri         = "$($configuration.GrafanaUri)/datasources/name/$DatasourceName" 
                    Headers     = $header
                    ContentType = "application/json"

                }

                If($PSCmdlet.ShouldProcess("Datasource Name:$DatasourceName","DELETE")){
                    
                    Invoke-RestMethod @irmParams
                
                }

            }

        }

    }

}
function Set-GrafanaConfig {
    <#
        .SYNOPSIS
        Modifies the configuration file for the module
         
        .PARAMETER ConfigurationFile
        The path to the JSON configuration file. Defaults to Config\Grafana.json
         
        .PARAMETER APIKey
        Your new API Key
         
        .PARAMETER GrafanaUri
        The new Grafana uri
         
        .EXAMPLE
        Set-GrafanaConfig -APIKey '10395j23oi2r' -GrafanaUri 'https://test-grafana.mydomain.org'
 
    #>

    [cmdletBinding()]
    Param(
        [Parameter()]
        [String]
        $ConfigurationFile = "$PSScriptRoot\Config\Grafana.json",

        [Parameter()]
        [String]
        $APIKey,

        [Parameter()]
        [String]
        $GrafanaUri
    )


    begin { $config = Get-GrafanaConfig }

    process {

        Switch($PSBoundParameters.Keys){

            'APIKey' {
                $config.apikey = $APIKey
            }

            'GrafanaUri' { 
                $config.GrafanaUri = $GrafanaUri
            }
        }

        $config | ConvertTo-Json | Set-Content $ConfigurationFile
    }
}
$PublicFunctions = 'Get-GrafanaAlert', 'Get-GrafanaApiKey', 'Get-GrafanaConfig', 'Get-GrafanaDashboard', 'Get-GrafanaDatasource', 'Get-GrafanaServerHealth', 'New-GrafanaAPIKey', 'New-GrafanaSnapshot', 'New-GraphanaPanel', 'Remove-GrafanaApiKey', 'Remove-GrafanaDatasource', 'Set-GrafanaConfig'
If(!(Test-Path $PSScriptRoot\Config\Grafana.json)){
    $grafanaConfig = @{
        
    }
    Write-Host "No config file found in Config folder. Assuming first run..." -ForegroundColor yellow
    Write-Host "We will now ask some questions to get things setup" -ForegroundColor yellow
    $GrafanaUri = Read-Host -Prompt "What is your base Grafana uri?"

    Write-Host "Adding URI and appending /api to config file..." -ForegroundColor yellow
    $grafanaConfig.Add('GrafanaUri',"$GrafanaUri/api")

    $ApiKey = Read-Host -Prompt "What is your API Key? Found at https://$GrafanaUri/org/apikeys"

    Write-Host "Adding API Key to config file..." -ForegroundColor yellow
    $grafanaConfig.Add('apikey',$ApiKey)

    $grafanaConfig | ConvertTo-Json | Out-File $PSScriptRoot\Config\Grafana.json

    Write-Host "Config file has been generated successfully. Run 'Get-GrafanaConfig' to verify" -ForegroundColor yellow
    
}