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()]
    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
    #>

    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 C:\Configs\Grafana.json
         
    #>

    [CmdletBinding()]
    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 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()]
    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
    @Adilio made me use ## to generate this and I feel dirty
     
    #>

    
    [cmdletBinding()]
    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
 
    #>

    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
    #>

    [cmdletBinding()]
    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

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

        }


        Invoke-RestMethod @irmParams
        
        $data = Invoke-RestMethod @irmParams
        $NewApiKey = $data.key
        Write-Information "API Key has been generated successfully"
        Write-Information "This is the only time you'll be able to view the API key."
        Write-Information "The key as been put into the $NewApiKey variable automatically"
        Write-Information "Please make note of this key for your records, should you need it."

        $data | Format-List

    }


}
function New-GrafanaSnapshot {

    [cmdletBinding()]
    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")]
    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")]
    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
    
}