├── .gitignore ├── Assets └── PSGrafana.png ├── Build ├── PSGrafana-Template.psm1 ├── build.ps1 ├── build.yml └── release.ps1 ├── LICENSE ├── PSGrafana ├── .DS_Store ├── PSGrafana.psd1 ├── PSGrafana.psm1 ├── Private │ └── .keep ├── Public │ ├── Get-GrafanaAlert.ps1 │ ├── Get-GrafanaAnnotation.ps1 │ ├── Get-GrafanaApiKey.ps1 │ ├── Get-GrafanaConfig.ps1 │ ├── Get-GrafanaDashboard.ps1 │ ├── Get-GrafanaDatasource.ps1 │ ├── Get-GrafanaFolder.ps1 │ ├── Get-GrafanaOrg.ps1 │ ├── Get-GrafanaOrgUser.ps1 │ ├── Get-GrafanaServerHealth.ps1 │ ├── Get-GrafanaServerSettings.ps1 │ ├── Get-GrafanaSnapshot.ps1 │ ├── Get-GrafanaUser.ps1 │ ├── New-GrafanaAPIKey.ps1 │ ├── New-GrafanaDashboard.ps1 │ ├── New-GrafanaFolder.ps1 │ ├── New-GrafanaSnapshot.ps1 │ ├── New-GraphanaPanel.ps1 │ ├── Remove-GrafanaApiKey.ps1 │ ├── Remove-GrafanaDashboard.ps1 │ ├── Remove-GrafanaDatasource.ps1 │ ├── Remove-GrafanaFolder.ps1 │ ├── Remove-GrafanaSnapshot.ps1 │ ├── Set-GrafanaConfig.ps1 │ ├── Set-GrafanaDashboard.ps1 │ ├── Set-GrafanaFolder.ps1 │ ├── Set-GrafanaUser.ps1 │ └── Suspend-GrafanaAlert.ps1 └── README.md ├── README.md └── Test └── Validation.Tests.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | *.json 2 | buildlocal.ps1 3 | PSGrafana-build/** 4 | Build/release-notes.txt 5 | Build/release-version.txt 6 | Build/Output 7 | Build/*.zip 8 | .DS_Store -------------------------------------------------------------------------------- /Assets/PSGrafana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steviecoaster/PSGrafana/ade068963c90774885a104b05eccac89068613b1/Assets/PSGrafana.png -------------------------------------------------------------------------------- /Build/PSGrafana-Template.psm1: -------------------------------------------------------------------------------- 1 | $PSGrafanaConfigPath = "$ENV:USERPROFILE/.psgrafana" 2 | If (!(Test-Path $PSGrafanaConfig)) { 3 | 4 | $null = New-Item -Path $PSGrafanaConfigPath -ItemType Directory 5 | 6 | $grafanaConfig = @{ 7 | 8 | } 9 | 10 | Write-Host "No config file found in Config folder. Assuming first run..." -ForegroundColor yellow 11 | Write-Host "We will now ask some questions to get things setup" -ForegroundColor yellow 12 | $GrafanaUri = Read-Host -Prompt "What is your base Grafana uri?" 13 | 14 | Write-Host "Adding URI and appending /api to config file..." -ForegroundColor yellow 15 | $grafanaConfig.Add('GrafanaUri', "$GrafanaUri/api") 16 | 17 | $ApiKey = Read-Host -Prompt "What is your API Key? Found at https://$GrafanaUri/org/apikeys" 18 | 19 | Write-Host "Adding API Key to config file..." -ForegroundColor yellow 20 | $grafanaConfig.Add('apikey', $ApiKey) 21 | 22 | $grafanaConfig | ConvertTo-Json | Out-File "$PSGrafanaConfigPath/Grafana.json" -Force 23 | 24 | Write-Host "Config file has been generated successfully. Run 'Get-GrafanaConfig' to verify" -ForegroundColor yellow 25 | 26 | } -------------------------------------------------------------------------------- /Build/build.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [switch] 4 | $Bootstrap, 5 | 6 | [switch] 7 | $Compile, 8 | 9 | [switch] 10 | $Test, 11 | 12 | [switch] 13 | $Deploy 14 | 15 | ) 16 | 17 | # Bootstrap step 18 | if ($Bootstrap.IsPresent) { 19 | Write-Information "Validate and install missing prerequisits for building ..." 20 | 21 | # For testing Pester 22 | if (-not (Get-Module -Name Pester -ListAvailable)) { 23 | Write-Warning "Module 'Pester' is missing. Installing 'Pester' ..." 24 | Install-Module -Name Pester -Scope CurrentUser -Force 25 | } 26 | 27 | # For tweeting 28 | if (-not (Get-Module -Name PSTwitterAPI -ListAvailable)) { 29 | Write-Warning "Module 'PSTwitterAPI' is missing. Installing 'PSTwitterAPI' ..." 30 | Install-Module -Name PSTwitterAPI -Scope CurrentUser -Force 31 | } 32 | 33 | } 34 | 35 | # Compile step 36 | if ($Compile.IsPresent) { 37 | if (Get-Module PSGrafana) { 38 | Remove-Module PSGrafana -Force 39 | } 40 | 41 | if ((Test-Path .\Output)) { 42 | Remove-Item -Path .\Output -Recurse -Force 43 | } 44 | 45 | # Copy non-script files to output folder 46 | if (-not (Test-Path .\Output)) { 47 | $null = New-Item -Path .\Output -ItemType Directory 48 | } 49 | 50 | Copy-Item -Path '.\PSGrafana\*' -Filter '*.*' -Exclude '*.ps1', '*.psm1' -Recurse -Destination .\Output -Force 51 | Remove-Item -Path .\Output\Private, .\Output\Public -Recurse -Force 52 | 53 | # Copy Module README file 54 | Copy-Item -Path '.\README.md' -Destination .\Output -Force 55 | 56 | Get-ChildItem -Path ".\PSGrafana\Private\*.ps1" -Recurse | Get-Content | Add-Content .\Output\PSGrafana.psm1 57 | 58 | $Public = @( Get-ChildItem -Path ".\PSGrafana\Public\*.ps1" -ErrorAction SilentlyContinue ) 59 | 60 | $Public | Get-Content | Add-Content .\Output\PSGrafana.psm1 61 | 62 | 63 | 64 | "`$PublicFunctions = '$($Public.BaseName -join "', '")'" | Add-Content .\Output\PSGrafana.psm1 65 | 66 | 67 | 68 | Remove-Item -Path .\PSGrafana -Recurse -Force 69 | Rename-Item -Path .\Output -NewName 'PSGrafana' 70 | 71 | # Compress output, for GitHub release 72 | Compress-Archive -Path .\PSGrafana\* -DestinationPath .\Build\PSGrafana.zip 73 | 74 | # Re-import module, extract release notes and version 75 | Import-Module .\PSGrafana\PSGrafana.psd1 -Force 76 | (Get-Module PSGrafana)[0].ReleaseNotes | Add-Content .\Build\release-notes.txt 77 | (Get-Module PSGrafana)[0].Version.ToString() | Add-Content .\Build\release-version.txt 78 | 79 | Get-Content -Path .\Build\PSGrafana-Template.psm1 | Add-Content .\PSGrafana\PSGrafana.psm1 80 | } 81 | 82 | # Test step 83 | if($Test.IsPresent) { 84 | if (-not (Get-Module -Name Pester -ListAvailable)) { 85 | throw "Cannot find the 'Pester' module. Please specify '-Bootstrap' to install build dependencies." 86 | } 87 | 88 | Install-Module -Name Pester -RequiredVersion 4.3.1 -Scope CurrentUser -Force -SkipPublisherCheck 89 | 90 | $RelevantFiles = (Get-ChildItem $PSScriptRoot -Recurse -Include "*.psm1","*.ps1").FullName 91 | 92 | $RelevantFiles = (Get-ChildItem $PSScriptRoot -Recurse -Include "*.psm1","*.ps1").FullName 93 | 94 | if ($env:TF_BUILD) { 95 | $res = Invoke-Pester ".\Test" -OutputFormat NUnitXml -OutputFile TestResults.xml -CodeCoverage $RelevantFiles -PassThru 96 | if ($res.FailedCount -gt 0) { throw "$($res.FailedCount) tests failed." } 97 | } else { 98 | $res = Invoke-Pester ".\Test\Validation.Tests.ps1" -PassThru 99 | } 100 | 101 | } 102 | 103 | #Deploy step 104 | if($Deploy.IsPresent) { 105 | 106 | [version]$currentVersion = Get-Content .\Build\release-version.txt 107 | 108 | Write-Host $currentVersion 109 | 110 | if($currentVersion.Minor -eq 1 -and $currentVersion.Build -eq 0) { 111 | 112 | $newVersion = "0.1.1" 113 | Update-ModuleManifest -Path .\PSGrafana\PSGrafana.psd1 -ModuleVersion $([version]$newVersion) 114 | 115 | } 116 | 117 | else { 118 | 119 | $newVersion = $currentVersion.Build + 1 120 | Update-ModuleManifest -Path .\PSGrafana\PSGrafana.psd1 -ModuleVersion $([version]"0.1.$newVersion") 121 | 122 | } 123 | 124 | Try { 125 | $Splat = @{ 126 | Path = (Resolve-Path -Path .\PSGrafana) 127 | NuGetApiKey = $env:NugetAPIKey 128 | ErrorAction = 'Stop' 129 | } 130 | Publish-Module @Splat 131 | 132 | 133 | Write-Output -InputObject ('PSGrafana PowerShell Module published to the PowerShell Gallery') 134 | 135 | } Catch { 136 | throw $_ 137 | } 138 | } -------------------------------------------------------------------------------- /Build/build.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | branches: 3 | include: 4 | - master 5 | exclude: 6 | - develop 7 | pr: 8 | branches: 9 | include: 10 | - master 11 | 12 | 13 | jobs: 14 | - job: PrepPSGrafana 15 | displayName: 'Prep PSGrafana' 16 | pool: 17 | vmImage: 'VS2017-Win2016' 18 | 19 | steps: 20 | - task: PowerShell@2 21 | displayName: 'Run tests (individual .ps1 files)' 22 | inputs: 23 | targetType: Inline 24 | script: .\Build\build.ps1 -Bootstrap -Test 25 | condition: succeededOrFailed() 26 | 27 | - task: PowerShell@2 28 | displayName: 'Compile module' 29 | inputs: 30 | targetType: Inline 31 | script: .\Build\build.ps1 -Compile 32 | condition: succeededOrFailed() 33 | 34 | - task: PowerShell@2 35 | displayName: 'Run tests (compiled .psm1)' 36 | inputs: 37 | targetType: Inline 38 | script: .\Build\build.ps1 -Test 39 | condition: succeededOrFailed() 40 | 41 | - task: PublishTestResults@2 42 | displayName: 'Publish test results' 43 | inputs: 44 | testRunner: NUnit 45 | testResultsFiles: '**\TestResults.xml' 46 | condition: succeededOrFailed() 47 | 48 | - task: PublishPipelineArtifact@0 49 | displayName: 'Publish compiled module artifact' 50 | inputs: 51 | artifactName: 'PSGrafana' 52 | targetPath: .\PSGrafana 53 | condition: succeededOrFailed() 54 | 55 | - task: PublishPipelineArtifact@0 56 | displayName: 'Publish Pipelines scripts as artifact' 57 | inputs: 58 | artifactName: 'PipelinesScripts' 59 | targetPath: .\Build 60 | condition: succeededOrFailed() 61 | 62 | - task: PowerShell@2 63 | condition: eq(variables['Build.SourceBranch'], 'refs/heads/master') 64 | displayName: 'Publish PSGrafana To PSGallery' 65 | inputs: 66 | targetType: Inline 67 | script: .\Build\build.ps1 -Deploy 68 | condition: succeeded() 69 | env: 70 | NugetAPIKey: $(NugetAPIKey) -------------------------------------------------------------------------------- /Build/release.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [switch] 4 | $Bootstrap, 5 | 6 | [switch] 7 | $DefineTag, 8 | 9 | [switch] 10 | $Publish, 11 | 12 | [switch] 13 | $Tweet 14 | ) 15 | 16 | # Bootstrap step 17 | if ($Bootstrap.IsPresent) { 18 | Write-Information "Validate and install missing prerequisits for building ..." 19 | 20 | # For tweeting 21 | if (-not (Get-Module -Name PSTwitterAPI -ListAvailable)) { 22 | Write-Warning "Module 'PSTwitterAPI' is missing. Installing 'PSTwitterAPI' ..." 23 | Install-Module -Name PSTwitterAPI -Scope CurrentUser -Force 24 | } 25 | } 26 | 27 | # Define Tag step 28 | if ($DefineTag.IsPresent) { 29 | $ReleaseVersion = Get-Content -Path $env:ArtifactDir\PipelinesScripts\release-version.txt 30 | Write-Host "##vso[task.setvariable variable=RELEASETAG]$ReleaseVersion" 31 | } 32 | 33 | # Publish step 34 | if ($Publish.IsPresent) { 35 | # Publish Module to PowerShell Gallery 36 | Try { 37 | $Splat = @{ 38 | Path = (Resolve-Path -Path $env:ArtifactDir\BurntToast) 39 | NuGetApiKey = $env:PSGallery 40 | ErrorAction = 'Stop' 41 | } 42 | Publish-Module @Splat 43 | 44 | Write-Output -InputObject ('BurntToast PowerShell Module published to the PowerShell Gallery') 45 | } Catch { 46 | throw $_ 47 | } 48 | } 49 | 50 | # Tweet step 51 | if($Tweet.IsPresent) { 52 | if (-not (Get-Module -Name PSTwitterAPI -ListAvailable)) { 53 | throw "Cannot find the 'PSTwitterAPI' module. Please specify '-Bootstrap' to install release dependencies." 54 | } 55 | 56 | Import-Module -Name PSTwitterAPI 57 | 58 | $OAuthSettings = @{ 59 | ApiKey = $env:TwitterConsumerKey 60 | ApiSecret = $env:TwitterConsumerSecret 61 | AccessToken = $env:TwitterAccessToken 62 | AccessTokenSecret = $env:TwitterAccessSecret 63 | } 64 | 65 | Set-TwitterOAuthSettings @OAuthSettings 66 | 67 | $ReleaseVersion = Get-Content -Path $env:ArtifactDir\PipelinesScripts\release-version.txt 68 | 69 | $Tweet = "Guys! PSGrafana v$ReleaseVersion is pushed to the #PowerShell Gallery via @AzureDevOps!$([System.Environment]::NewLine)$([System.Environment]::NewLine)$([System.Environment]::NewLine)https://www.powershellgallery.com/packages/PSGrafana/$ReleaseVersion" 70 | 71 | Send-TwitterStatuses_Update -status $Tweet 72 | 73 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Stephen Valdinger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PSGrafana/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steviecoaster/PSGrafana/ade068963c90774885a104b05eccac89068613b1/PSGrafana/.DS_Store -------------------------------------------------------------------------------- /PSGrafana/PSGrafana.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'PSGrafana' 3 | # 4 | # Generated by: Stephen Valdinger 5 | # 6 | # Generated on: 3/17/19 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | RootModule = 'PSGrafana.psm1' 13 | 14 | # Version number of this module. 15 | ModuleVersion = '0.1.0' 16 | 17 | # Supported PSEditions 18 | #CompatiblePSEditions = @('Core','5.1') 19 | 20 | 21 | # ID used to uniquely identify this module 22 | GUID = 'dd2b7af6-c1df-498d-9019-a166b3a8db48' 23 | 24 | # Author of this module 25 | Author = 'Stephen Valdinger' 26 | 27 | # Company or vendor of this module 28 | CompanyName = 'Unknown' 29 | 30 | # Copyright statement for this module 31 | Copyright = '(c) Stephen Valdinger. All rights reserved.' 32 | 33 | # Description of the functionality provided by this module 34 | Description = 'This module enables you to interact with Grafana via its REST API' 35 | 36 | # Minimum version of the PowerShell engine required by this module 37 | # PowerShellVersion = '' 38 | 39 | # Name of the PowerShell host required by this module 40 | # PowerShellHostName = '' 41 | 42 | # Minimum version of the PowerShell host required by this module 43 | # PowerShellHostVersion = '' 44 | 45 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 46 | # DotNetFrameworkVersion = '' 47 | 48 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 49 | # CLRVersion = '' 50 | 51 | # Processor architecture (None, X86, Amd64) required by this module 52 | # ProcessorArchitecture = '' 53 | 54 | # Modules that must be imported into the global environment prior to importing this module 55 | # RequiredModules = @() 56 | 57 | # Assemblies that must be loaded prior to importing this module 58 | # RequiredAssemblies = @() 59 | 60 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 61 | # ScriptsToProcess = @() 62 | 63 | # Type files (.ps1xml) to be loaded when importing this module 64 | # TypesToProcess = @() 65 | 66 | # Format files (.ps1xml) to be loaded when importing this module 67 | # FormatsToProcess = @() 68 | 69 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 70 | # NestedModules = @() 71 | 72 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 73 | FunctionsToExport = @('Get-GrafanaConfig', 74 | 'Set-GrafanaConfig', 75 | 'Get-GrafanaDashboard', 76 | 'New-GrafanaDashboard', 77 | 'Remove-GrafanaDashboard', 78 | 'Set-GrafanaDashboard', 79 | 'Get-GrafanaServerHealth', 80 | 'Get-GrafanaAnnotation', 81 | 'New-GrafanaAPIKey', 82 | 'Get-GrafanaApiKey', 83 | 'New-GrafanaApiKey', 84 | 'Remove-GrafanaApiKey', 85 | 'Get-GrafanaDatasource', 86 | 'Remove-GrafanaDatasource', 87 | 'Get-GrafanaSnapshot', 88 | 'New-GrafanaSnapshot', 89 | 'Remove-GrafanaSnapshot', 90 | 'Get-GrafanaAlert', 91 | 'Suspend-GrafanaAlert', 92 | 'Get-GrafanaFolder', 93 | 'New-GrafanaFolder', 94 | 'Set-GrafanaFolder', 95 | 'Remove-GrafanaFolder', 96 | 'Get-GrafanaOrg', 97 | 'Get-GrafanaOrgUser' 98 | 'Get-GrafanaUser', 99 | 'Set-GrafanaUser', 100 | 'Get-GrafanaServerSettings' 101 | ) 102 | 103 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 104 | CmdletsToExport = '*' 105 | 106 | # Variables to export from this module 107 | VariablesToExport = '*' 108 | 109 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 110 | AliasesToExport = '*' 111 | 112 | # DSC resources to export from this module 113 | # DscResourcesToExport = @() 114 | 115 | # List of all modules packaged with this module 116 | # ModuleList = @() 117 | 118 | # List of all files packaged with this module 119 | # FileList = @() 120 | 121 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 122 | PrivateData = @{ 123 | 124 | PSData = @{ 125 | 126 | # Tags applied to this module. These help with module discovery in online galleries. 127 | Tags = @('Grafana', 'PowershellCore', 'GrafanaAPI', 'Monitoring', 'Metrics', 'Dashboard') 128 | 129 | # A URL to the license for this module. 130 | LicenseUri = 'https://github.com/steviecoaster/PSGrafana/LICENSE.md' 131 | 132 | # A URL to the main website for this project. 133 | # ProjectUri = '' 134 | 135 | # A URL to an icon representing this module. 136 | # IconUri = '' 137 | 138 | # ReleaseNotes of this module 139 | 140 | ReleaseNotes = 'This release brings the cmdlet count up to 20! Consider this the first beta release!' 141 | 142 | } # End of PSData hashtable 143 | 144 | } # End of PrivateData hashtable 145 | 146 | # HelpInfo URI of this module 147 | # HelpInfoURI = '' 148 | 149 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 150 | # DefaultCommandPrefix = '' 151 | 152 | } 153 | 154 | -------------------------------------------------------------------------------- /PSGrafana/PSGrafana.psm1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steviecoaster/PSGrafana/ade068963c90774885a104b05eccac89068613b1/PSGrafana/PSGrafana.psm1 -------------------------------------------------------------------------------- /PSGrafana/Private/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steviecoaster/PSGrafana/ade068963c90774885a104b05eccac89068613b1/PSGrafana/Private/.keep -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaAlert.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaAlert { 2 | <# 3 | .SYNOPSIS 4 | Query Grafana API for alert information 5 | 6 | .PARAMETER DashboardId 7 | The ID of the dashboard to query 8 | 9 | .PARAMETER DashboardName 10 | The friendly name of the dashboard to query 11 | 12 | .PARAMETER DashboardTag 13 | Search for alerts belong to a dashboard with a specific tag 14 | 15 | .PARAMETER AlertName 16 | Query for all alerts matching the alert name 17 | 18 | .PARAMETER State 19 | Query for all alerts in the state of 'ALL','no_data','paused', 'alerting','ok','pending' 20 | 21 | .EXAMPLE 22 | Get-GrafanaAlert 23 | 24 | .EXAMPLE 25 | Get-GranaAlert -DashboardId 1 26 | 27 | .EXAMPLE 28 | Get-GrafanaAlert -DashboardName "PeterRabbit" 29 | 30 | .EXAMPLE 31 | Get-GrafanaAlert -DashboardTag 'prod' 32 | 33 | .EXAMPLE 34 | Get-GrafanaAlert -AlertName 'Perrywinkle' 35 | 36 | .EXAMPLE State 37 | Get-GrafanaAlert -State 'paused' 38 | 39 | #> 40 | 41 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaAlert")] 42 | Param( 43 | 44 | [Parameter()] 45 | [Int[]] 46 | $DashboardId, 47 | 48 | [Parameter()] 49 | [String] 50 | $DashboardName, 51 | 52 | [Parameter()] 53 | [String[]] 54 | $DashboardTag, 55 | 56 | [Parameter()] 57 | [Alias('Query')] 58 | [String] 59 | $AlertName, 60 | 61 | [Parameter()] 62 | [String[]] 63 | [ValidateSet('ALL','no_data','paused', 'alerting','ok','pending')] 64 | $State 65 | ) 66 | 67 | begin { $null = Get-GrafanaConfig } 68 | 69 | process { 70 | 71 | $irmParams = @{ 72 | headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 73 | Method = "GET" 74 | ContentType = "application/json" 75 | } 76 | 77 | If($PSBoundParameters.Count -eq 0){ 78 | 79 | $irmParams.Add("Uri","$($configuration.GrafanaUri)/alerts") 80 | } 81 | 82 | Else { 83 | 84 | Switch($PSBoundParameters.Keys){ 85 | 86 | "DashboardName" { 87 | 88 | $irmParams.Add("Uri","$($configuration.GrafanaUri)/alerts?dashboardQuery=$Dashboardname") 89 | 90 | } 91 | 92 | "DashboardId" { 93 | 94 | $url = "$($configuration.GrafanaUri)/alerts?" 95 | foreach ($id in $DashboardId) { 96 | $url += "dashboardId={0}&" -f $id 97 | } 98 | $irmParams.Add("Uri","$($url -replace ".$")") 99 | 100 | } 101 | 102 | "DashboardTag" { 103 | 104 | $url = "$($configuration.GrafanaUri)/alerts?" 105 | foreach ($id in $DashboardTag) { 106 | $url += "dashboardTag={0}&" -f $id 107 | } 108 | $irmParams.Add("Uri","$($url -replace ".$")") 109 | 110 | } 111 | 112 | "State" { 113 | 114 | $url = "$($configuration.GrafanaUri)/alerts?" 115 | foreach ($id in $State) { 116 | $url += "state={0}&" -f $id 117 | } 118 | $irmParams.Add("Uri","$($url -replace ".$")") 119 | 120 | } 121 | 122 | "Alertname" { 123 | 124 | $irmParams.Add("Uri","$($configuration.GrafanaUri)/alerts?query=$AlertName") 125 | 126 | } 127 | 128 | }#switch 129 | 130 | }#else 131 | 132 | $irmParams['Uri'] 133 | $result = Invoke-RestMethod @irmParams 134 | 135 | $result 136 | 137 | }#process 138 | 139 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaAnnotation.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaAnnotation { 2 | <# 3 | .SYNOPSIS 4 | Retrieves annotations via the Grafana API 5 | 6 | .DESCRIPTION 7 | Search for various types of annotations via the Grafana API 8 | 9 | .PARAMETER From 10 | The start time to search 11 | 12 | .PARAMETER To 13 | The end time to search 14 | 15 | .PARAMETER AlertName 16 | The specific alert annotation you want to find 17 | 18 | .PARAMETER DashboardName 19 | The specific dashboard to return results for 20 | 21 | .PARAMETER PanelName 22 | The specific panel to retrieve results for 23 | 24 | .PARAMETER Username 25 | The specific username to search for 26 | 27 | .PARAMETER Type 28 | Retrieve annotations of a certain type 29 | 30 | .PARAMETER Tags 31 | Retrieve annotation based on tags 32 | 33 | .PARAMETER All 34 | Return all annotations 35 | 36 | .PARAMETER Credential 37 | The Grafana credentials to use to retrieve annotations 38 | 39 | .EXAMPLE 40 | Get-GrafanaAnnotation -All -Credential $cred 41 | 42 | .EXAMPLE 43 | Get-GrafanaAnnotation -DashboardName WebServer 44 | 45 | .EXAMPLE 46 | Get-GrafanaAnnotation -Username bob 47 | 48 | #> 49 | 50 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaAnnotation")] 51 | Param( 52 | [Parameter(Mandatory,Position=0,ParameterSetName="time")] 53 | [String] 54 | $From, 55 | 56 | [Parameter(Mandatory,Position=1,ParameterSetName="time")] 57 | [string] 58 | $To, 59 | 60 | [Parameter(Mandatory,Position=0,ParameterSetName="alert")] 61 | [String] 62 | $AlertName, 63 | 64 | [Parameter(Mandatory,Position=0,ParameterSetName="dashboard")] 65 | [String] 66 | $DashboardName, 67 | 68 | [Parameter(Mandatory,Position=0,ParameterSetName="panel")] 69 | [String] 70 | $PanelName, 71 | 72 | [Parameter(Mandatory,Position=0,ParameterSetName="user")] 73 | [String] 74 | $Username, 75 | 76 | [Parameter(Mandatory,Position=0,ParameterSetName="type")] 77 | [ValidateSet("Alert","Annotation")] 78 | [String] 79 | $Type, 80 | 81 | [Parameter(Mandatory,Position=0,ParameterSetName="tags")] 82 | [String[]] 83 | $Tags, 84 | 85 | [Parameter(Mandatory,Position=0,ParameterSetName="all")] 86 | [Switch] 87 | $All, 88 | 89 | [Parameter(Mandatory,Position=1,ParameterSetName="all")] 90 | [Parameter(Mandatory,Position=2,ParameterSetName="time")] 91 | [Parameter(Mandatory,Position=1,ParameterSetName="alert")] 92 | [Parameter(Mandatory,Position=1,ParameterSetName="dashboard")] 93 | [Parameter(Mandatory,Position=1,ParameterSetName="panel")] 94 | [Parameter(Mandatory,Position=1,ParameterSetName="user")] 95 | [Parameter(Mandatory,Position=1,ParameterSetName="type")] 96 | [Parameter(Mandatory,Position=1,ParameterSetName="tags")] 97 | [PSCredential] 98 | $Credential 99 | 100 | ) 101 | 102 | begin { $null = Get-GrafanaConfig } 103 | 104 | process { 105 | 106 | $irmParams = @{ 107 | 108 | Method = "GET" 109 | ContentType = "application/json" 110 | Authentication = "Basic" 111 | Credential = $Credential 112 | 113 | } 114 | 115 | If($($configuration.GrafanaUri) -match '^(http://)'){ 116 | 117 | $irmParams.Add('AllowUnencryptedAuthentication',$true) 118 | 119 | } 120 | 121 | 122 | Switch($PSCmdlet.ParameterSetName){ 123 | 124 | 'time' {} 125 | 'alert' { 126 | 127 | $alertId = Get-GrafanaAlert | Where-Object { $_.Name -eq "$AlertName" } | Select -ExpandProperty id 128 | 129 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/annotations?alertId=$alertID") 130 | 131 | } 132 | 'dashboard' { 133 | 134 | $dashboardId = Get-GrafanaDashboard | Where-Object { $_.title -eq "$DashboardName"} | Select-Object -ExpandProperty id 135 | 136 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/annotations?dashboardId=$dashboardId") 137 | 138 | } 139 | 'panel' {} 140 | 'user' { 141 | 142 | $userId = Get-GrafanaUser -Username $Username | Select-Object -ExpandProperty id 143 | 144 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/annotations?userId=$userId") 145 | 146 | } 147 | 'type' { 148 | 149 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/annotations?type=$($Type.ToLower())") 150 | 151 | } 152 | 'tags' { 153 | 154 | $uri = @("$($configuration.GrafanaUri)/annotations?tags=") 155 | 156 | $tags = $Tags -join "&tags=" 157 | 158 | Write-Host $uri$tags 159 | 160 | $irmParams.Add('Uri',"$uri$tags") 161 | 162 | 163 | } 164 | 165 | 'all' { 166 | 167 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/annotations") 168 | 169 | } 170 | } 171 | 172 | $result = Invoke-RestMethod @irmParams 173 | 174 | $result 175 | 176 | } 177 | 178 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaApiKey.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaApiKey { 2 | <# 3 | .SYNOPSIS 4 | Retrieve a list of API keys created in Grafana 5 | 6 | .EXAMPLE 7 | Get-GrafanaApiKey 8 | #> 9 | [cmdletBinding(HelpUri="ttps://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaApiKey")] 10 | Param() 11 | 12 | begin { $null = Get-GrafanaConfig } 13 | 14 | process { 15 | 16 | $header = @{ Authorization = "Bearer $($Configuration.apikey)"} 17 | 18 | $irmParams = @{ 19 | Method = 'GET' 20 | Uri = "$($Configuration.GrafanaUri)/auth/keys" 21 | Headers = $header 22 | ContentType = "application/json" 23 | 24 | } 25 | 26 | Invoke-RestMethod @irmParams 27 | } 28 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaConfig.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaConfig { 2 | <# 3 | .SYNOPSIS 4 | Reads the Grafana.json file and returns an object 5 | 6 | .PARAMETER ConfigurationFile 7 | The path to the configuration json. Defaults to Config\Grafana.json 8 | 9 | .EXAMPLE 10 | Get-GrafanaConfig 11 | 12 | .EXAMPLE 13 | Get-GrafanaConfig -ConfigurationFile C:\Configs\Grafana.json 14 | 15 | #> 16 | [CmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaConfig")] 17 | Param( 18 | [Parameter(Position=0)] 19 | [String] 20 | 21 | $ConfigurationFile = "$ENV:USERPROFILE/.psgrafana/Grafana.json" 22 | 23 | ) 24 | 25 | begin {} 26 | 27 | process { 28 | 29 | $Global:Configuration = Get-Content $ConfigurationFile | ConvertFrom-Json 30 | 31 | $Configuration 32 | 33 | } 34 | 35 | end {} 36 | 37 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaDashboard.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaDashboard { 2 | <# 3 | .SYNOPSIS 4 | Returns an object with details about a Grafana dashboard 5 | 6 | .PARAMETER Name 7 | Search the Grafana instance for dashboards by friendly name 8 | 9 | .PARAMETER Uuid 10 | Search the Grafana instance for dashboards by UID 11 | 12 | .PARAMETER Tag 13 | Search the Grafana instance for dashboards by Tag 14 | 15 | .PARAMETER IncludeMetadata 16 | Include extra metadata about the dashboard. Excluded by default. 17 | 18 | .EXAMPLE 19 | Get-GrafanaDashboard -Name 'Prod - FileServer' 20 | 21 | .EXAMPLE 22 | Get-GrafanaDashboard -Uuid O0E3f5t 23 | 24 | .EXAMPLE 25 | Get-GrafanaDashboard -Name 'Smiley' -IncudeMetadata 26 | 27 | #> 28 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaDashboard",DefaultParameterSetName="All")] 29 | Param( 30 | 31 | [Parameter(Position=0,ParameterSetName='All')] 32 | [Switch] 33 | $All, 34 | 35 | [Parameter(Position=0,ParameterSetName='Name')] 36 | [String] 37 | $Name, 38 | 39 | [Parameter(Position=0,ParameterSetName='Uuid')] 40 | [String] 41 | $Uuid, 42 | 43 | [Parameter(Position=0,ParameterSetName='Tag')] 44 | [String] 45 | $Tag, 46 | 47 | [Parameter()] 48 | [Switch] 49 | $IncludeMetadata 50 | ) 51 | 52 | begin { $null = Get-GrafanaConfig } 53 | 54 | process { 55 | 56 | $header = @{ Authorization = "Bearer $($Configuration.apikey)"} 57 | 58 | Switch($PSCmdlet.ParameterSetName){ 59 | 60 | 'Name' { 61 | 62 | $irmParams = @{ 63 | 64 | Method = "GET" 65 | Uri = "$($configuration.GrafanaUri)/search?query=$Name" 66 | Headers = $header 67 | ContentType = "application/json" 68 | 69 | } 70 | 71 | $result = Invoke-RestMethod @irmParams 72 | 73 | $result 74 | 75 | } 76 | 77 | 'Uuid' { 78 | 79 | $irmParams = @{ 80 | 81 | Method = "GET" 82 | Uri = "$($configuration.GrafanaUri)/dashboards/uid/$uuid" 83 | Headers = $header 84 | ContentType = "application/json" 85 | 86 | } 87 | 88 | $result = Invoke-RestMethod @irmParams 89 | 90 | If($IncludeMetadata){ 91 | 92 | $result | Format-List 93 | 94 | } 95 | 96 | Else { 97 | 98 | $result.dashboard 99 | } 100 | 101 | } 102 | 103 | 'Tag' { 104 | 105 | $irmParams = @{ 106 | 107 | Method = "GET" 108 | Uri = "$($configuration.GrafanaUri)/search?tag=$Tag" 109 | Headers = $header 110 | ContentType = "application/json" 111 | 112 | } 113 | 114 | $result = Invoke-RestMethod @irmParams 115 | 116 | $result.Content | ConvertFrom-Json 117 | 118 | } 119 | 120 | 'All' { 121 | 122 | $irmParams = @{ 123 | 124 | Method = "GET" 125 | Uri = "$($configuration.GrafanaUri)/search?type=dash-db" 126 | Headers = $header 127 | ContentType = "application/json" 128 | 129 | } 130 | 131 | $result = Invoke-RestMethod @irmParams 132 | 133 | $result 134 | 135 | } 136 | 137 | 138 | }#switch 139 | 140 | 141 | }#process 142 | 143 | }#function -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaDatasource.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaDatasource { 2 | <# 3 | .SYNOPSIS 4 | Fetch information about Grafana datasources via the API 5 | 6 | .PARAMETER All 7 | Returns all datasources in your Grafana Instance 8 | 9 | .PARAMETER DatasourceId 10 | The ID of the datasource for which to search 11 | 12 | .PARAMETER DatasourceName 13 | The friendly name of the datasource for which to search 14 | 15 | .EXAMPLE 16 | Get-GrafanaDatasource -All 17 | 18 | .EXAMPLE 19 | Get-GrafanaDatasource -DatasourceId 4 20 | 21 | .EXAMPLE 22 | Get-GrafanaDatasource -Datasourcename ElasticPuppies 23 | 24 | .NOTES 25 | 26 | #> 27 | 28 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaDatasource")] 29 | Param( 30 | [Parameter()] 31 | [Switch] 32 | $All, 33 | 34 | [Parameter()] 35 | [Int] 36 | $DatasourceId, 37 | 38 | [Parameter()] 39 | [String] 40 | $DatasourceName 41 | 42 | ) 43 | 44 | begin { $null = Get-GrafanaConfig } 45 | 46 | process { 47 | 48 | $header = @{ Authorization = "Bearer $($Configuration.apikey)"} 49 | 50 | If($All){ 51 | 52 | $irmParams = @{ 53 | 54 | Method = "GET" 55 | Uri = "$($configuration.GrafanaUri)/datasources" 56 | Headers = $header 57 | ContentType = "application/json" 58 | 59 | } 60 | 61 | $result = Invoke-RestMethod @irmParams 62 | 63 | $result 64 | } 65 | 66 | Switch($PSBoundParameters.Keys){ 67 | 68 | 'DatasourceId' { 69 | $irmParams = @{ 70 | 71 | Method = "GET" 72 | Uri = "$($configuration.GrafanaUri)/datasources/$DatasourceId" 73 | Headers = $header 74 | ContentType = "application/json" 75 | 76 | } 77 | 78 | $result = Invoke-RestMethod @irmParams 79 | 80 | $result 81 | } 82 | 83 | 'DatasourceName' { 84 | $irmParams = @{ 85 | 86 | Method = "GET" 87 | Uri = "$($configuration.GrafanaUri)/datasources/name/$DatasourceName" 88 | Headers = $header 89 | ContentType = "application/json" 90 | 91 | } 92 | 93 | $result = Invoke-RestMethod @irmParams 94 | 95 | $result 96 | 97 | } 98 | } 99 | 100 | } 101 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaFolder.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaFolder { 2 | <# 3 | .SYNOPSIS 4 | Retrieve folder information from Grafana via the API 5 | 6 | .DESCRIPTION 7 | You can search for Grafana folders via the API with this cmdlet. You may search via Uid,Id, or return All folders 8 | 9 | .PARAMETER Uid 10 | The UID value of a folder you wish to search for. This is an alphanumeric value 11 | 12 | .PARAMETER Id 13 | This is the ID of the folder you wish to search for. This is an int value 14 | 15 | .PARAMETER All 16 | Return all folders which you have access too. 17 | 18 | .EXAMPLE 19 | Get-GrafanaFolder 20 | 21 | Returns all folders which the user has access to in Grafana. 22 | 23 | .EXAMPLE 24 | Get-GrafanaFolder -Uid Ax8x33 25 | 26 | Returns the information for the folder with the Uid you entered 27 | 28 | .EXAMPLE 29 | Get-GrafanaFolder -Id 3 30 | 31 | Returns the information for the folder with the specified ID 32 | 33 | #> 34 | 35 | [cmdletBinding(HelpUri="hhttps://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaFolder",DefaultParameterSetName="All")] 36 | Param( 37 | [Parameter(ParameterSetName="Uid")] 38 | [String] 39 | $Uid, 40 | 41 | [Parameter(ParameterSetName="Id")] 42 | [Int] 43 | $Id, 44 | 45 | [Parameter(ParameterSetName="All")] 46 | [Switch] 47 | $All 48 | 49 | ) 50 | 51 | begin { $null = Get-GrafanaConfig } 52 | 53 | process { 54 | 55 | $irmParams = @{ 56 | 57 | Method = "GET" 58 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 59 | ContentType = "application/json" 60 | 61 | } 62 | 63 | Switch ($PSCmdlet.ParameterSetName) { 64 | 65 | 'Uid' { 66 | 67 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/folders/$Uid") 68 | 69 | } 70 | 71 | 'Id' { 72 | 73 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/folders/id/$Id") 74 | 75 | } 76 | 77 | default { 78 | 79 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/folders") 80 | 81 | } 82 | } 83 | 84 | $return = Invoke-RestMethod @irmParams 85 | 86 | $return 87 | 88 | } 89 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaOrg.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaOrg { 2 | <# 3 | .SYNOPSIS 4 | Returns information about Grafana Organizations 5 | 6 | .DESCRIPTION 7 | Returns information about various organizations configured in your Grafana installation. 8 | 9 | .PARAMETER OrgName 10 | Specify an Org name to retrieve information about that Org 11 | 12 | .PARAMETER CurrentOrg 13 | Retrieve information about the Current Org the user belongs too. 14 | 15 | .EXAMPLE 16 | Get-GrafanaOrg -OrgName Headquarters 17 | 18 | .EXAMPLE 19 | Get-GrafanaOrg -CurrentOrg 20 | 21 | #> 22 | 23 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaOrg")] 24 | Param( 25 | [Parameter()] 26 | [String] 27 | $OrgName, 28 | 29 | [Parameter()] 30 | [Switch] 31 | $CurrentOrg 32 | ) 33 | 34 | begin { $null = Get-GrafanaConfig } 35 | 36 | process { 37 | 38 | $irmParams = @{ 39 | 40 | Method = 'GET' 41 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 42 | ContentType = "application/json" 43 | 44 | } 45 | 46 | Switch($PSBoundParameters.Keys){ 47 | 48 | 'OrgName' { 49 | 50 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/orgs/name/$OrgName") 51 | 52 | } 53 | 54 | 'CurrentOrg' { 55 | 56 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/org") 57 | 58 | } 59 | 60 | } 61 | 62 | $return = Invoke-RestMethod @irmParams 63 | 64 | $return 65 | 66 | } 67 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaOrgUser.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaOrgUser { 2 | <# 3 | .SYNOPSIS 4 | Returns all users within the current org 5 | 6 | .DESCRIPTION 7 | Returns all users of the current org in the context of the API key token holder's context 8 | 9 | .EXAMPLE 10 | Get-GrafanaOrgUser 11 | 12 | #> 13 | 14 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaOrgUser")] 15 | Param( 16 | 17 | ) 18 | 19 | begin { $null = Get-GrafanaConfig } 20 | 21 | process { 22 | 23 | $irmParams = @{ 24 | 25 | Method = 'GET' 26 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 27 | ContentType = "application/json" 28 | Uri ="$($configuration.GrafanaUri)/org/users" 29 | 30 | } 31 | 32 | $return = Invoke-RestMethod @irmParams 33 | 34 | $return 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaServerHealth.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaServerHealth { 2 | <# 3 | 4 | .SYNOPSIS 5 | Returns Grafana server health info 6 | 7 | .EXAMPLE 8 | 9 | Get-GrafanaServerhealth 10 | 11 | #> 12 | 13 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaServerHealth")] 14 | Param() 15 | 16 | begin { $null = Get-GrafanaConfig} 17 | 18 | process { 19 | 20 | Invoke-RestMethod -Uri "$($Configuration.GrafanaUri)/health" 21 | 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaServerSettings.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaServerSettings { 2 | <# 3 | .SYNOPSIS 4 | Returns server settings for your Grafana Instance 5 | 6 | .DESCRIPTION 7 | Returns the currently configured settings for your Grafana instance. User must be an Org Admin to retrieve these settings 8 | 9 | .PARAMETER Credential 10 | The credentials you wish to use 11 | 12 | .EXAMPLE 13 | Get-GrafanaServerSettings 14 | 15 | #> 16 | 17 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaServerSettings")] 18 | Param( 19 | [Parameter(Mandatory,Position=0)] 20 | [PSCredential] 21 | $Credential 22 | ) 23 | 24 | begin { $null = Get-GrafanaConfig } 25 | 26 | process { 27 | 28 | $irmParams = @{ 29 | 30 | Method = 'GET' 31 | Authentication = "Basic" 32 | Credential = $Credential 33 | ContentType = "application/json" 34 | Uri = "$($configuration.Grafanauri)/admin/settings" 35 | } 36 | 37 | If($($configuration.GrafanaUri) -match '^(http://)'){ 38 | 39 | $irmParams.Add('AllowUnencryptedAuthentication',$true) 40 | 41 | } 42 | 43 | $result = Invoke-RestMethod @irmParams 44 | 45 | $result 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaSnapshot.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaSnapshot { 2 | <# 3 | .SYNOPSIS 4 | Retrieve Grafana Snapshots via API 5 | 6 | .DESCRIPTION 7 | Retrieve a single snapshot by Name, or return All snapshots 8 | 9 | .PARAMETER SnapshotName 10 | The friendly name of the Snapshot to retrieve 11 | 12 | .PARAMETER All 13 | Switch to return all snapshots 14 | 15 | .EXAMPLE 16 | Get-GrafanaSnapshot -SnapshotName SnappyMcSnapperson 17 | 18 | .EXAMPLE 19 | Get-GrafanaSnapshot -All 20 | 21 | #> 22 | 23 | [cmdletBinding(DefaultParameterSetName="Snapshot",HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaSnapshot")] 24 | Param( 25 | [Parameter(Mandatory,ParameterSetName="Snapshot")] 26 | [String] 27 | $SnapshotName, 28 | 29 | [Parameter(Mandatory,ParameterSetName="All")] 30 | [Switch] 31 | $All 32 | ) 33 | 34 | begin { $null = Get-GrafanaConfig } 35 | 36 | process { 37 | $irmParams = @{ 38 | 39 | Method = "GET" 40 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 41 | ContentType = "application/json" 42 | 43 | } 44 | 45 | Switch($PSCmdlet.ParameterSetName){ 46 | 47 | 'Snapshot' { 48 | 49 | $irmParams.Add("Uri","$($configuration.GrafanaUri)/dashboard/snapshots/?query=$SnapshotName") 50 | 51 | } 52 | 53 | 'All' { 54 | 55 | $irmParams.Add("Uri","$($configuration.GrafanaUri)/dashboard/snapshots") 56 | 57 | } 58 | } 59 | 60 | $result = Invoke-RestMethod @irmParams 61 | 62 | $result 63 | 64 | } 65 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Get-GrafanaUser.ps1: -------------------------------------------------------------------------------- 1 | function Get-GrafanaUser { 2 | <# 3 | .SYNOPSIS 4 | Return information about a Grafana user. 5 | 6 | .DESCRIPTION 7 | Search via Email Address or Username for information about the specified Grafana user. 8 | 9 | .PARAMETER Username 10 | The username to query information for 11 | 12 | .PARAMETER Credential 13 | The credentials to use when searching by username 14 | 15 | .PARAMETER EmailAddress 16 | The email address to query information for 17 | 18 | .EXAMPLE 19 | Get-GrafanaUser -EmailAddress bob@foo.com 20 | 21 | .EXAMPLE 22 | Get-GrafanaUser -Username bob -Credential grafana_admin 23 | 24 | You will be prompted to enter the password for grafana_admin 25 | 26 | .EXAMPLE 27 | Get-GrafanaUser -Username bob -Credential (Get-Credential) 28 | 29 | Provide the username and password of an org admin in Grafana to the Credential prompt 30 | 31 | .EXAMPLE 32 | Get-GrafanaUser -Username bob -Credential $Credential 33 | 34 | Use a stored Grafana org admin credential 35 | 36 | .NOTES 37 | General notes 38 | #> 39 | 40 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Get-GrafanaUser",DefaultParameterSetName="Email")] 41 | Param( 42 | 43 | [Parameter(Mandatory,ParameterSetName="Username")] 44 | [String] 45 | $Username, 46 | 47 | [Parameter(Position=0,Mandatory,ParameterSetName="Email")] 48 | [String] 49 | $EmailAddress, 50 | 51 | [Parameter(Position=0,Mandatory,ParameterSetName="All")] 52 | [Switch] 53 | $All, 54 | 55 | [Parameter(Mandatory,ParameterSetName="All")] 56 | [Parameter(Mandatory,ParameterSetName="Username")] 57 | [Parameter(Mandatory,ParameterSetName="Email")] 58 | [PSCredential] 59 | $Credential 60 | ) 61 | 62 | begin { $null = Get-GrafanaConfig } 63 | 64 | process { 65 | 66 | $irmParams = @{ 67 | 68 | Method = "GET" 69 | ContentType = "application/json" 70 | 71 | } 72 | 73 | If($($configuration.GrafanaUri) -match '^(http://)'){ 74 | 75 | $irmParams.Add('AllowUnencryptedAuthentication',$true) 76 | 77 | } 78 | 79 | Switch($PSCmdlet.ParameterSetName){ 80 | 81 | 'Username' { 82 | 83 | 84 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/users/search?query=$Username") 85 | $irmParams.Add('Authentication', "Basic") 86 | $irmParams.Add('Credential', $Credential) 87 | } 88 | 89 | 'Email' { 90 | 91 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/users/search?query=$EmailAddress") 92 | $irmParams.Add('Authentication', "Basic") 93 | $irmParams.Add('Credential', $Credential) 94 | 95 | } 96 | 97 | 'All' { 98 | 99 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/users/search") 100 | $irmParams.Add('Authentication', "Basic") 101 | $irmParams.Add('Credential', $Credential) 102 | 103 | 104 | } 105 | 106 | } 107 | 108 | $return = Invoke-RestMethod @irmParams 109 | 110 | $output = [System.Collections.Generic.List[pscustomobject]]::new() 111 | 112 | $return.users | ForEach-Object { $output.Add([pscustomobject]$_) } 113 | 114 | $output 115 | 116 | } 117 | 118 | } -------------------------------------------------------------------------------- /PSGrafana/Public/New-GrafanaAPIKey.ps1: -------------------------------------------------------------------------------- 1 | function New-GrafanaApiKey { 2 | <# 3 | .SYNOPSIS 4 | Creates a new API key in Grafana 5 | 6 | .PARAMETER Name 7 | The friendly name of the API key 8 | 9 | .PARAMETER Role 10 | The access level for the key. Available options are Admin,Editor, and Viewer 11 | 12 | .EXAMPLE 13 | New-GrafanaApiKey -Name RickyBobby -Role Admin 14 | 15 | .EXAMPLE 16 | New-GrafanaApiKey -Name Alice -Role Editor 17 | 18 | .NOTES 19 | The generated API key is only displayed at runtime. If you need to retain it for any reason, be sure to it somewhere safe. 20 | It is highly recommended you run this command saved to a variable such as $ApiKey = New-GrafanaApiKey -Name ElmerFudd -Role Viewer. 21 | This way you can access the properties Name and Key within the variable. E.g. $ApiKey.name, or $ApiKey.key. 22 | #> 23 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/New-GrafanaApiKey")] 24 | Param( 25 | 26 | [Parameter(Mandatory,Position=0)] 27 | [String] 28 | $Name, 29 | 30 | [Parameter(Mandatory,Position=1)] 31 | [ValidateSet('Admin','Viewer','Editor')] 32 | [String] 33 | $Role 34 | 35 | ) 36 | 37 | begin { 38 | 39 | $null = Get-GrafanaConfig 40 | 41 | } 42 | 43 | process { 44 | 45 | $header = @{ Authorization = "Bearer $($Configuration.apikey)"} 46 | $body = @{name = $Name; role = $Role} | ConvertTo-Json 47 | 48 | $irmParams = @{ 49 | Method = 'POST' 50 | Uri = "$($Configuration.GrafanaUri)/auth/keys" 51 | Body = "$body" 52 | Headers = $header 53 | ContentType = "application/json" 54 | 55 | } 56 | Write-Warning -Message "You'll only see the API key generated here one time. There is no method to retrieve/generate it." 57 | Invoke-RestMethod @irmParams 58 | 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /PSGrafana/Public/New-GrafanaDashboard.ps1: -------------------------------------------------------------------------------- 1 | function New-GrafanaDashboard { 2 | <# 3 | .SYNOPSIS 4 | Add a new dashboard to Grafana 5 | 6 | .DESCRIPTION 7 | This cmdlet adds a new dashboard to the specified folder inside of Grafana 8 | 9 | .PARAMETER Title 10 | The Title of the Dashbaord 11 | 12 | .PARAMETER Tags 13 | The tags you wish the Dashboard to use 14 | 15 | .PARAMETER Folder 16 | The folder in which to store the Dashboard in Grafana 17 | 18 | .EXAMPLE 19 | New-GrafanaDashboard -Title "My Awesome Dashboard" -Folder "Fancy Dashboards" 20 | 21 | .EXAMPLE 22 | New-GrafanaDashboard -Title "My Awesome Dashboard" -Tags "production","webserver","cats" -Folder Home 23 | 24 | #> 25 | 26 | [cmdletBinding(DefaultParameterSetName="New")] 27 | Param( 28 | [Parameter(Mandatory,ParameterSetName="New")] 29 | [String] 30 | $Title, 31 | 32 | [Parameter(ParameterSetName="New")] 33 | [String[]] 34 | $Tags, 35 | 36 | [Parameter(Mandatory,ParameterSetName="New")] 37 | [String] 38 | $Folder 39 | 40 | 41 | ) 42 | 43 | begin { $null = Get-GrafanaConfig } 44 | 45 | process { 46 | 47 | $irmParams = @{ 48 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 49 | ContentType = "application/json" 50 | Method = "POST" 51 | Uri = "$($configuration.GrafanaUri)/dashboards/db" 52 | } 53 | 54 | $body = @{} 55 | $dashboard = @{ 56 | 57 | title = "$Title" 58 | tags = $Tags 59 | 60 | } 61 | 62 | $FolderId = Get-GrafanaFolder | Where-Object { $_.title -eq $Folder } | Select-Object -ExpandProperty id 63 | 64 | $body.Add('folderId',$FolderId) 65 | $body.Add("overwrite",$false) 66 | $body.Add("dashboard",$dashboard) 67 | 68 | $dashboard.Add("id",$null) 69 | $dashboard.Add("uid",$null) 70 | 71 | $irmParams.Add('Body',($body | ConvertTo-Json)) 72 | 73 | $result = Invoke-RestMethod @irmParams 74 | 75 | $result 76 | 77 | }#process 78 | 79 | }#function -------------------------------------------------------------------------------- /PSGrafana/Public/New-GrafanaFolder.ps1: -------------------------------------------------------------------------------- 1 | function New-GrafanaFolder { 2 | <# 3 | .SYNOPSIS 4 | Create a new folder in Grafana via the API 5 | 6 | .DESCRIPTION 7 | The Grafana API allows you to create new folders. This cmdlet accomplishes this. Title is required, but you may supply an optional Uid. 8 | If you don't specify a Uid, one will be generated for you by the API at runtime. 9 | 10 | .PARAMETER Title 11 | The title of the folder you wish to create with the API 12 | 13 | .PARAMETER Uid 14 | The uid to give the folder when created by the API 15 | 16 | .EXAMPLE 17 | New-GrafanaFolder -Title "My Awesome Folder" 18 | 19 | Creates a new folder in Grafana called "My Awesome Folder" 20 | 21 | .EXAMPLE 22 | New-GrafanaFolder -Title "Web Farm Folder" -Uid nErXDvCkzz 23 | 24 | Creates a new folder in Grafana called "Web Farm Folder" with a Uid of nErXDvCkzz 25 | 26 | .NOTES 27 | General notes 28 | #> 29 | 30 | [CmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/New-GrafanaFolder")] 31 | Param( 32 | [Parameter(Mandatory,Position=0)] 33 | [String] 34 | $Title, 35 | 36 | [Parameter(Position=1)] 37 | [String] 38 | $Uid 39 | ) 40 | 41 | begin { $null = Get-GrafanaConfig } 42 | 43 | process { 44 | 45 | $body = @{ 46 | 47 | title = $Title 48 | 49 | } 50 | 51 | If($Uid){ 52 | 53 | $body.Add('uid',$Uid) 54 | } 55 | 56 | $irmParams = @{ 57 | 58 | Method = "POST" 59 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 60 | Uri = "$($Configuration.GrafanaUri)/folders" 61 | ContentType = "application/json" 62 | Body = $body | ConvertTo-Json 63 | 64 | } 65 | 66 | Invoke-RestMethod @irmParams 67 | 68 | } 69 | } -------------------------------------------------------------------------------- /PSGrafana/Public/New-GrafanaSnapshot.ps1: -------------------------------------------------------------------------------- 1 | function New-GrafanaSnapshot { 2 | <# 3 | .SYNOPSIS 4 | Take a snapshot of a dashboard in Grafana 5 | 6 | .PARAMETER DashboardTitle 7 | Title of the dashboard you wish to snapshot 8 | 9 | .PARAMETER SnapshotName 10 | Name of the snapshot you are creating 11 | 12 | .PARAMETER Expires 13 | Time (in seconds) the snapshot stays alive. Set to 0 to never expire. 14 | 15 | .EXAMPLE 16 | New-GrafanaSnapshot -DashboardTitle WebHosts -SnapshotName WebSnap -Expires 0 17 | 18 | Create a new snapshot of WebHosts with the name WebSnap that never expires 19 | #> 20 | 21 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/New-GrafanaSnapshot")] 22 | Param( 23 | 24 | [Parameter(Mandatory,Position=0)] 25 | [String] 26 | $DashboardTitle, 27 | 28 | [Parameter(Mandatory,Position=1)] 29 | [String] 30 | $SnapshotName, 31 | 32 | [Parameter(Position=0)] 33 | [Int] 34 | $Expires = 0 35 | ) 36 | 37 | begin { $null = Get-GrafanaConfig} 38 | 39 | process { 40 | 41 | 42 | $irmParams = @{ 43 | 44 | headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 45 | body= @{ 46 | 47 | dashboard = [ordered]@{ 48 | editable = $False 49 | hideControls = $True 50 | nav = @(@{enable=$False 51 | type = 'timepicker'}) 52 | rows = @(@{}) 53 | style = "dark" 54 | tags = @() 55 | templating = @{list = @()} 56 | time = @{} 57 | timezone = "browser" 58 | title = "$DashboardTitle" 59 | version = 5 60 | } 61 | expires = $Expires 62 | name = "$SnapshotName" 63 | 64 | } | ConvertTo-Json -Depth 4 65 | Method = "POST" 66 | Uri = "$($configuration.GrafanaUri)/snapshots" 67 | ContentType = "application/json" 68 | 69 | 70 | } 71 | 72 | Invoke-RestMethod @irmParams 73 | 74 | } 75 | } -------------------------------------------------------------------------------- /PSGrafana/Public/New-GraphanaPanel.ps1: -------------------------------------------------------------------------------- 1 | function New-GraphanaGraphPanel { 2 | 3 | [cmdletBinding()] 4 | Param( 5 | [Parameter(Mandatory,Position=0)] 6 | [String] 7 | $Title, 8 | 9 | [Parameter(Mandatory,Position=1)] 10 | [String] 11 | $Description, 12 | 13 | [Parameter(Mandatory,Position=2)] 14 | [String] 15 | $Datasource, 16 | 17 | [Parameter(Mandatory,Position=3)] 18 | [String] 19 | [ValidateSet('graph','singlestat','gauge','table','text','heatmap','alert list','dashboard list','plugin list')] 20 | $Type, 21 | 22 | [Parameter()] 23 | [Switch] 24 | $Transparent, 25 | 26 | [Parameter()] 27 | [Array] 28 | $valueMappings, 29 | 30 | [Parameter()] 31 | [Switch] 32 | $showThresholdLabels, 33 | 34 | [Parameter()] 35 | [Switch] 36 | $showThresholdMarkers, 37 | 38 | [Parameter()] 39 | [Int] 40 | $minValue, 41 | 42 | [Parameter()] 43 | [int] 44 | $thresholds_Index, 45 | 46 | [Parameter()] 47 | [string] 48 | $threshold_HexColor, 49 | 50 | [Parameter()] 51 | [int] 52 | $threshold_Value 53 | 54 | 55 | 56 | ) 57 | 58 | begin {} 59 | 60 | process { 61 | $panelHash = @{ 62 | 63 | } 64 | 65 | } 66 | 67 | end {} 68 | 69 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Remove-GrafanaApiKey.ps1: -------------------------------------------------------------------------------- 1 | function Remove-GrafanaApiKey { 2 | <# 3 | .SYNOPSIS 4 | Deletes an API key from your Grafana Instance 5 | 6 | .PARAMETER ApiId 7 | The ID of the API Key you wish to delete 8 | 9 | .EXAMPLE 10 | Remove-GrafanaApiKey -ApiId 6 11 | 12 | #> 13 | 14 | [cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High",HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Remove-GrafanaApiKey")] 15 | Param( 16 | 17 | [Parameter(Mandatory,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)] 18 | [Int] 19 | $ApiId 20 | 21 | ) 22 | 23 | begin { $Null = Get-GrafanaConfig } 24 | 25 | process { 26 | 27 | If($PSCmdlet.ShouldProcess("ID: $ApiId","DELETE")){ 28 | 29 | $header = @{ Authorization = "Bearer $($Configuration.apikey)"} 30 | 31 | $irmParams = @{ 32 | 33 | Method = "DELETE" 34 | Uri = "$($Configuration.GrafanaUri)/auth/keys/$ApiId" 35 | Headers = $header 36 | ContentType = "application/json" 37 | } 38 | 39 | Invoke-RestMethod @irmParams 40 | 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Remove-GrafanaDashboard.ps1: -------------------------------------------------------------------------------- 1 | function Remove-GrafanaDashboard { 2 | <# 3 | .SYNOPSIS 4 | Remove a Grafana Dashboard via the API 5 | 6 | .DESCRIPTION 7 | This cmdlet exposes the API to delete a dashboard out of Grafana 8 | 9 | .PARAMETER Dashboard 10 | The friendly name of the Dashbaord to remove. 11 | 12 | .EXAMPLE 13 | Remove-GrafanaDashboard -Name FancyDash 14 | 15 | .EXAMPLE 16 | Get-GrafanaDashboard -Name FancyDash | Remove-GrafanaDashboard 17 | 18 | .EXAMPLE 19 | Remove-GrafanaDashbaord -Name WebFarmDev -Confirm:$false 20 | 21 | #> 22 | 23 | [cmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="Default")] 24 | Param( 25 | [Parameter(Mandatory,Position=0,ParameterSetName="Default")] 26 | [Alias('Name')] 27 | [String] 28 | $Dashboard, 29 | 30 | [Parameter(Mandatory,ParameterSetName="Pipeline",ValueFromPipeline)] 31 | [PSObject] 32 | $InputObject 33 | 34 | 35 | ) 36 | 37 | begin { $null = Get-GrafanaConfig } 38 | 39 | process { 40 | 41 | Switch($PSCmdlet.ParameterSetName){ 42 | 43 | 'Default' { 44 | 45 | $Uid = Get-GrafanaDashboard -Name $Dashboard | Select-Object -ExpandProperty uid 46 | 47 | } 48 | 49 | 'Pipeline' { 50 | 51 | $Uid = $($InputObject.uid) 52 | 53 | } 54 | 55 | } 56 | 57 | $irmParams = @{ 58 | Method = "DELETE" 59 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 60 | ContentType = "application/json" 61 | Uri = "$($configuration.GrafanaUri)/dashboards/uid/$Uid" 62 | } 63 | 64 | If($PSCmdlet.ShouldProcess("Dashboard: $Dashboard", "DELETE")){ 65 | $Result = Invoke-RestMethod @irmParams 66 | 67 | $Result 68 | 69 | } 70 | 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Remove-GrafanaDatasource.ps1: -------------------------------------------------------------------------------- 1 | function Remove-GrafanaDatasource { 2 | <# 3 | .SYNOPSIS 4 | Removes the specified Grafana datasource 5 | 6 | .PARAMETER DatasourceId 7 | The ID of the datasource you wish to remove 8 | 9 | .PARAMETER DatasourceName 10 | The friendly name of the datasouce you wish to remove 11 | 12 | .EXAMPLE 13 | Remove-GrafanaDashboard -DatasourceId 3 14 | 15 | .EXAMPLE 16 | Remove-GrafanaDashboard -DatasourceName 'ElasticPuppies' 17 | #> 18 | [cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High",HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Remove-GrafanaDatasource")] 19 | param( 20 | 21 | [Parameter()] 22 | [Int] 23 | $DatasourceId, 24 | 25 | [Parameter()] 26 | [String] 27 | $DatasourceName 28 | ) 29 | 30 | begin { $null = Get-GrafanaConfig } 31 | 32 | process { 33 | 34 | $header = @{ Authorization = "Bearer $($Configuration.apikey)"} 35 | 36 | Switch($PSBoundParameters.Keys){ 37 | 38 | 'DatasourceId' { 39 | 40 | $irmParams = @{ 41 | 42 | Method = "DELETE" 43 | Uri = "$($configuration.GrafanaUri)/datasources/$DatasourceId" 44 | Headers = $header 45 | ContentType = "application/json" 46 | 47 | } 48 | 49 | If($PSCmdlet.ShouldProcess("DELETE","Datasource ID:$DatasourceId")){ 50 | 51 | Invoke-RestMethod @irmParams 52 | 53 | } 54 | } 55 | 56 | 'DatasourceName' { 57 | 58 | $irmParams = @{ 59 | 60 | Method = "DELETE" 61 | Uri = "$($configuration.GrafanaUri)/datasources/name/$DatasourceName" 62 | Headers = $header 63 | ContentType = "application/json" 64 | 65 | } 66 | 67 | If($PSCmdlet.ShouldProcess("Datasource Name:$DatasourceName","DELETE")){ 68 | 69 | Invoke-RestMethod @irmParams 70 | 71 | } 72 | 73 | } 74 | 75 | } 76 | 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Remove-GrafanaFolder.ps1: -------------------------------------------------------------------------------- 1 | function Remove-GrafanaFolder { 2 | <# 3 | .SYNOPSIS 4 | Removes the specified folder from your Grafana instance 5 | 6 | .DESCRIPTION 7 | Removes the specified folder from your Grafana instance using the API. This is a highly destructive operation. Any Panels that are stored within the folder will be destroyed. 8 | 9 | .PARAMETER Folder 10 | The folder you wish to delete 11 | 12 | .EXAMPLE 13 | Remove-GrafanaFolder -Folder Duckies 14 | 15 | #> 16 | 17 | [cmdletBinding(SupportsShouldProcess,ConfirmImpact="High")] 18 | Param( 19 | 20 | [Parameter(Mandatory,Position=0)] 21 | [String] 22 | $Folder 23 | ) 24 | 25 | begin { $null = Get-GrafanaConfig } 26 | 27 | process { 28 | 29 | $Uid = Get-GrafanaFolder | Where-Object { $_.title -eq "$Folder" } | Select-Object -ExpandProperty uid 30 | 31 | $irmParams = @{ 32 | 33 | Method = "DELETE" 34 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 35 | ContentType = "application/json" 36 | Uri = "$($configuration.GrafanaUri)/folders/$Uid" 37 | 38 | } 39 | 40 | If($PSCmdlet.ShouldProcess("Folder: $Folder", "DELETE")){ 41 | $return = Invoke-RestMethod @irmParams 42 | 43 | $return 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Remove-GrafanaSnapshot.ps1: -------------------------------------------------------------------------------- 1 | function Remove-GrafanaSnapshot { 2 | <# 3 | .SYNOPSIS 4 | Remove a Grafana snapshot via the API 5 | 6 | .DESCRIPTION 7 | Grafana exposes an endpoint to delete snapshots. This cmdlet leverages that endpoint to let you remove them programmatically 8 | 9 | .PARAMETER SnapshotName 10 | The friendly name of the snapshot you wish to remove 11 | 12 | .EXAMPLE 13 | Remove-GrafanaSnapshot -SnapshotName SnappyMcSnapshoterson 14 | 15 | #> 16 | 17 | [cmdletBinding(SupportsShouldProcess,ConfirmImpact="High")] 18 | Param( 19 | 20 | [Parameter(Mandatory)] 21 | [String] 22 | $SnapshotName 23 | 24 | ) 25 | 26 | begin { $null = Get-GrafanaConfig } 27 | 28 | process { 29 | 30 | $Key = Get-GrafanaSnapshot -SnapshotName $SnapshotName | Select-Object -ExpandProperty key 31 | 32 | $irmParams = @{ 33 | 34 | Method = "DELETE" 35 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 36 | ContentType = "application/json" 37 | Uri = "$($configuration.GrafanaUri)/snapshots/$key" 38 | 39 | } 40 | 41 | If($PSCmdlet.ShouldProcess("Snapshot: $SnapshotName", "DELETE")){ 42 | 43 | Invoke-RestMethod @irmParams 44 | 45 | } 46 | 47 | }#process 48 | 49 | }#function -------------------------------------------------------------------------------- /PSGrafana/Public/Set-GrafanaConfig.ps1: -------------------------------------------------------------------------------- 1 | function Set-GrafanaConfig { 2 | <# 3 | .SYNOPSIS 4 | Modifies the configuration file for the module 5 | 6 | .PARAMETER ConfigurationFile 7 | The path to the JSON configuration file. Defaults to Config\Grafana.json 8 | 9 | .PARAMETER APIKey 10 | Your new API Key 11 | 12 | .PARAMETER GrafanaUri 13 | The new Grafana uri 14 | 15 | .EXAMPLE 16 | Set-GrafanaConfig -APIKey '10395j23oi2r' -GrafanaUri 'https://test-grafana.mydomain.org' 17 | 18 | #> 19 | [cmdletBinding()] 20 | Param( 21 | [Parameter()] 22 | [String] 23 | $ConfigurationFile = "$ENV:USERPROFILE/.psgrafana/Grafana.json", 24 | 25 | [Parameter()] 26 | [String] 27 | $APIKey, 28 | 29 | [Parameter()] 30 | [String] 31 | $GrafanaUri 32 | ) 33 | 34 | 35 | begin { $config = Get-GrafanaConfig } 36 | 37 | process { 38 | 39 | Switch($PSBoundParameters.Keys){ 40 | 41 | 'APIKey' { 42 | $config.apikey = $APIKey 43 | } 44 | 45 | 'GrafanaUri' { 46 | $config.GrafanaUri = $GrafanaUri 47 | } 48 | } 49 | 50 | $config | ConvertTo-Json | Set-Content $ConfigurationFile 51 | } 52 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Set-GrafanaDashboard.ps1: -------------------------------------------------------------------------------- 1 | function Set-GrafanaDashboard { 2 | <# 3 | .SYNOPSIS 4 | Update an existing Dashboard in Grafana 5 | 6 | .DESCRIPTION 7 | Change the title and tags of an existing Dashboard in Grafana 8 | 9 | .PARAMETER Title 10 | The title of the dashboard you wish to modify 11 | 12 | .PARAMETER NewTitle 13 | The new title of the Dashboard if you wish to change it 14 | 15 | .PARAMETER Tags 16 | The updated tags. This overwrites existing tags 17 | 18 | .PARAMETER DashboardId 19 | If you know the dashboard ID, you may enter it 20 | 21 | .PARAMETER DashboardUid 22 | If you know the dashboard Uid, you may enter it 23 | 24 | .EXAMPLE 25 | Set-GrafanaDashboard -Title "Boring Old Title" -NewTitle "Fancy New Title" 26 | 27 | .EXAMPLE 28 | Set-GrafanaDashboard -Title "Boring Old Title" -NewTitle "Fancy New Title" -Tags "prod","wizz_bang" 29 | 30 | .EXAMPLE 31 | Set-GrafanaDashboard -Title "Boring Old Title" -Tags "prod","apache" -DashboardId 35 -DashboardUid 5XWS256 32 | 33 | #> 34 | 35 | [cmdletBinding(DefaultParameterSetName="Update")] 36 | Param( 37 | [Parameter(Mandatory,Position=0,ParameterSetName="Update")] 38 | [String] 39 | $Title, 40 | 41 | [Parameter(Position=1,ParameterSetName="Update")] 42 | [String] 43 | $NewTitle, 44 | 45 | [Parameter(ParameterSetName="Update")] 46 | [String[]] 47 | $Tags, 48 | 49 | [Parameter(Mandatory,ParameterSetName="id")] 50 | [Int] 51 | $DashboardId, 52 | 53 | [Parameter(Mandatory,ParameterSetName="id")] 54 | [String] 55 | $DashboardUid 56 | ) 57 | 58 | begin { $null = Get-GrafanaConfig } 59 | 60 | process { 61 | 62 | $irmParams = @{ 63 | 64 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 65 | ContentType = "application/json" 66 | Method = "POST" 67 | Uri = "$($configuration.GrafanaUri)/dashboards/db" 68 | 69 | } 70 | 71 | $body = @{ 72 | 73 | overwrite = $true 74 | 75 | } 76 | $dashboard = @{} 77 | 78 | if($NewTitle){ 79 | 80 | $dashboard.Add("title",$NewTitle) 81 | 82 | } 83 | 84 | else{ 85 | 86 | $dashboard.Add("title",$Title) 87 | 88 | } 89 | 90 | If($PSCmdlet.ParameterSetName -eq "id"){ 91 | 92 | $dashboard.Add("id",$DashboardId) 93 | $dashboard.Add("uid",$DashboardUid) 94 | 95 | } 96 | 97 | else{ 98 | 99 | $identifiers = Get-GrafanaDashboard -Name $Title | Select-Object id,uid,folderid 100 | 101 | $dashboard.Add("id",$identifiers.id) 102 | $dashboard.Add("uid",$identifiers.uid) 103 | 104 | $body.Add('folderId',$identifiers.folderid) 105 | 106 | } 107 | 108 | $body.Add("dashboard",$dashboard) 109 | 110 | $irmParams.Add("Body",($body | ConvertTo-Json)) 111 | 112 | $return = Invoke-RestMethod @irmParams 113 | 114 | $return 115 | 116 | } 117 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Set-GrafanaFolder.ps1: -------------------------------------------------------------------------------- 1 | function Set-GrafanaFolder { 2 | <# 3 | .SYNOPSIS 4 | Update the Title of a Folder in Grafana 5 | 6 | .DESCRIPTION 7 | The API only allows updates to the Title of a folder in Grafana. This cmdlet accomplishes that task 8 | 9 | .PARAMETER OldTitle 10 | The current title of the Folder you wish to change 11 | 12 | .PARAMETER NewTitle 13 | The new title of the folder you wish to change 14 | 15 | .EXAMPLE 16 | Set-GrafanaFolder -OldTitle "FooBar" -NewTitle "FizzBuzz" 17 | 18 | Set the title of the folder FooBar to FizzBuzz 19 | 20 | .NOTES 21 | 22 | #> 23 | 24 | [cmdletBinding(HelpUri="https://github.com/steviecoaster/PSGrafana/wiki/Set-GrafanaFolder",SupportsShouldProcess=$true,ConfirmImpact="High")] 25 | Param( 26 | [Parameter(Mandatory,Position=0)] 27 | [String] 28 | $OldTitle, 29 | 30 | [Parameter(Mandatory,Position=1)] 31 | [String] 32 | $NewTitle 33 | ) 34 | 35 | begin { $null = Get-GrafanaConfig } 36 | 37 | process { 38 | 39 | $Uid = Get-GrafanaFolder | Where-Object { $_.title -eq "$OldTitle" } | Select-Object -ExpandProperty uid 40 | $Version = Get-GrafanaFolder -Uid $uid | Select-Object -ExpandProperty version 41 | 42 | Write-Warning -Message "Modifying folder with Uid: $Uid and Version: $Version" 43 | 44 | $irmParams = @{ 45 | 46 | Method = "PUT" 47 | Headers = @{ Authorization = "Bearer $($Configuration.apikey)"} 48 | ContentType = "application/json" 49 | Uri = "$($configuration.GrafanaUri)/folders/$Uid?overwrite=true" 50 | Body = (@{Title = $NewTitle}| ConvertTo-Json) 51 | 52 | } 53 | 54 | If($PSCmdlet.ShouldProcess("Folder: $OldTitle", "UPDATE")){ 55 | 56 | Invoke-RestMethod @irmParams 57 | 58 | } 59 | 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /PSGrafana/Public/Set-GrafanaUser.ps1: -------------------------------------------------------------------------------- 1 | function Set-GrafanaUser { 2 | [cmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory,Position=0)] 5 | [String] 6 | $Username, 7 | 8 | [Parameter(Position=1)] 9 | [ValidateSet('default','light','dark')] 10 | [String] 11 | $Theme, 12 | 13 | [Parameter(Position=2)] 14 | [String] 15 | $FullName, 16 | 17 | [Parameter(Position=3)] 18 | [String] 19 | $EmailAddress, 20 | 21 | [Parameter(Position=4)] 22 | [String] 23 | $NewUsername, 24 | 25 | [Parameter(Mandatory,Position=5)] 26 | [PSCredential] 27 | $Credential 28 | 29 | ) 30 | 31 | begin { $null = Get-GrafanaConfig } 32 | 33 | process { 34 | 35 | $User = Get-GrafanaUser -Username $Username -Credential $Credential 36 | 37 | $irmParams = @{ 38 | 39 | Method = 'PUT' 40 | Authentication = "Basic" 41 | Credential = $Credential 42 | ContentType = "application/json" 43 | 44 | } 45 | 46 | If($($configuration.GrafanaUri) -match '^(http://)'){ 47 | 48 | $irmParams.Add('AllowUnencryptedAuthentication',$true) 49 | 50 | } 51 | 52 | $body = @{} 53 | 54 | Switch($PSBoundParameters.Keys){ 55 | 56 | 'Username' { 57 | 58 | $irmParams.Add('Uri',"$($configuration.GrafanaUri)/users/$($User.users.id)") 59 | $body.Add("login","$Username") 60 | 61 | } 62 | 63 | 'Theme' { 64 | 65 | $body.Add('theme',"$Theme") 66 | } 67 | 68 | 'FullName' { 69 | 70 | $body.Add("name","$FullName") 71 | 72 | } 73 | 74 | 'EmailAddress' { 75 | 76 | $body.Add("email","$EmailAddress") 77 | 78 | } 79 | 80 | 'NewUsername' { 81 | 82 | $body.Add("login","$NewUsername") 83 | 84 | } 85 | 86 | }#switch 87 | 88 | $body | ConvertTo-Json 89 | 90 | $irmParams.Add("body",($body | ConvertTo-Json)) 91 | 92 | $result = Invoke-RestMethod @irmParams 93 | 94 | $result 95 | 96 | }#process 97 | 98 | }#function -------------------------------------------------------------------------------- /PSGrafana/Public/Suspend-GrafanaAlert.ps1: -------------------------------------------------------------------------------- 1 | function Suspend-GrafanaAlert { 2 | <# 3 | .SYNOPSIS 4 | Pause a Grafana Alert by Name, ID, or pause ALL alerts in Grafana 5 | 6 | .DESCRIPTION 7 | This cmdlet provides a way to pause Grafana alerts via the API 8 | 9 | .PARAMETER AlertId 10 | The ID of the Grafana Alert you wish to pause 11 | 12 | .PARAMETER AlertName 13 | The Name of the Grafana Alert you wish to pause 14 | 15 | .PARAMETER All 16 | Pause all Grafana Alerts 17 | 18 | .PARAMETER Credential 19 | The credential to use to pause all Grafana alerts 20 | 21 | .EXAMPLE 22 | Suspend-GrafanaAlert -AlertId 12 23 | 24 | .EXAMPLE 25 | Suspend-GrafanaAlert -AlertName WebResponseTime 26 | 27 | .EXAMPLE 28 | Suspend-GrafanaAlert -All -Credential _username_ 29 | 30 | .EXAMPLE 31 | Suspend-GrafanaAlert -All -Credential (Get-Credential) 32 | 33 | .NOTES 34 | The -Credential parameter is required when pausing all alerts. This is due to how the API handles the authentication header for that operation 35 | 36 | #> 37 | 38 | [cmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="Name")] 39 | Param( 40 | [Parameter(ParameterSetName="Id")] 41 | [Int] 42 | $AlertId, 43 | 44 | [Parameter(ParameterSetName="Name")] 45 | [String] 46 | $AlertName, 47 | 48 | [Parameter(Mandatory,Position=0,ParameterSetName="All")] 49 | [Switch] 50 | $All, 51 | 52 | [Parameter(Mandatory,Position=1,ParameterSetName="All")] 53 | [System.Management.Automation.PSCredential] 54 | $Credential 55 | 56 | ) 57 | 58 | begin { $null = Get-GrafanaConfig } 59 | 60 | process { 61 | 62 | function Test-Uri($uri) { 63 | 64 | $null = $uri -match '^((?http://)|(?https://))' 65 | 66 | } 67 | 68 | Test-Uri -uri $configuration.GrafanaUri 69 | 70 | $irmParams = @{ 71 | 72 | Method = "POST" 73 | ContentType = "application/json" 74 | Body = @{'paused' = $true} | ConvertTo-Json 75 | 76 | } 77 | 78 | Switch($PSCmdlet.ParameterSetName){ 79 | 80 | 'Id' { 81 | $irmParams.Add('Uri',"$($Configuration.GrafanaUri)/alerts/$AlertId/pause") 82 | $irmParams.Add("Headers",@{ Authorization = "Bearer $($Configuration.apikey)"}) 83 | 84 | If($PSCmdlet.ShouldProcess("Alert: $AlertId", "PAUSE")){ 85 | 86 | $result = Invoke-RestMethod @irmParams 87 | $result 88 | } 89 | } 90 | 91 | 'Name' { 92 | 93 | $Name = (Get-GrafanaAlert -AlertName $AlertName).id 94 | 95 | $irmParams.Add('Uri',"$($Configuration.GrafanaUri)/alerts/$Name/pause") 96 | $irmParams.Add("Headers",@{ Authorization = "Bearer $($Configuration.apikey)"}) 97 | 98 | If($PSCmdlet.ShouldProcess("Alert: $Alertname", "PAUSE")){ 99 | 100 | $result = Invoke-RestMethod @irmParams 101 | $result 102 | } 103 | 104 | } 105 | 106 | 'All' { 107 | 108 | 109 | $irmParams.Add("Uri","$($configuration.GrafanaUri)/admin/pause-all-alerts") 110 | $irmParams.Add("Authentication","Basic") 111 | $irmParams.Add("Credential",$Credential) 112 | 113 | If($($configuration.GrafanaUri) -match '^(http://)'){ 114 | 115 | $irmParams.Add('AllowUnencryptedAuthentication',$true) 116 | 117 | } 118 | 119 | If($PSCmdlet.ShouldProcess("Alert: $Alertname", "PAUSE")){ 120 | 121 | $result = Invoke-RestMethod @irmParams 122 | $result 123 | } 124 | 125 | } 126 | } 127 | 128 | }#process 129 | 130 | }#function -------------------------------------------------------------------------------- /PSGrafana/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | # PSGrafana 4 | 5 | The PSGrafana module is a PowerShell wrapper around the Grafana API. Grafana uses this API internally for everything you do in the web interface. It made sense to create a wrapper such that you could bolt Grafana tasks to any automation pipelines one might have in their organizations. 6 | 7 | ## Status 8 | 9 | The module is currently in development, and as such expect rapid changes, specifically on the `develop` branch. The master branch will only contain code that has been deemed "working" and triggers the pipeline to publish new module versions. 10 | 11 | --- 12 | 13 | ## Contributing 14 | 15 | If you would like to help out, please target the `develop` branch when creating pull requests, otherwise the pipeline will have a bad time and we'll end up with stuff hitting the gallery too early. 16 | 17 | --- 18 | 19 | ## Currently available functions include: 20 | 21 | - Get-GrafanaConfig 22 | - Set-GrafanaConfig 23 | - Get-GrafanaDashboard 24 | - New-GrafanaDashboard 25 | - Set-GrafanaDashboard 26 | - Remove-GrafanaDashboard 27 | - Get-GrafanaServerHealth 28 | - Get-GrafanaApiKey 29 | - Get-GrafanaDatasource 30 | - Remove-GrafanaDatasource 31 | - Remove-GrafanaApiKey 32 | - New-GrafanaApiKey 33 | - New-GrafanaSnapshot 34 | - Get-GrafanaSnapshot 35 | - Remove-GrafanaSnapshot 36 | - Get-GrafanaAlert 37 | - Suspend-GrafanaAlert 38 | - New-GrafanaFolder 39 | - Get-GrafanaFolder 40 | - Remove-GrafanaFolder 41 | 42 | --- 43 | 44 | ## Installation 45 | 46 | #### Github: 47 | 48 | Option 1: 49 | 50 | Clone this repository. Import the psd1 file from the directory with `Import-module ./PSGrafana.psd1` or the full path to the psd1 file if outside the cloned directory. 51 | 52 | Option 2: 53 | 54 | Clone the repository somewhere in your $PSModulePath, and then run `Import-Module PSGrafana` 55 | 56 | Option 3: 57 | 58 | Download the zip archive and extract it on your machine and reference Option 1 or 2 above based on where you extract it too. 59 | 60 | #### Powershell Gallery 61 | 62 | This module is available via the Powershell Gallery. The latest released version is v0.0.4. 63 | 64 | To install simply run `Install-Module PSGrafana` 65 | 66 | _IMPORTANT NOTE REGARDING INSTALLATION:_ 67 | 68 | Upon first run, a configuration file will be generated for you by asking a series of questions. Namely: 69 | 70 | - What is your Grafana instance URL? 71 | - What is your Grafana instance API key? 72 | 73 | Once provided a Grafana.json file will be generated in your user profile in the `.psgrafana` directory. All functions pull in this configuration in their `begin {}` blocks to reference the global $configuration variable. 74 | 75 | --- 76 | 77 | ## Issues? 78 | 79 | Did you find a bug? Awesome! I wanna know about it. Please file an issue providing as much information as possible. 80 | Did you find a bug, _and_ fix the bug? Awesome! Thanks so much! Please file the detailed issue, and submit a PR for review. Be sure to add 'Fixes _issue\_number_' at the bottom of the PR notes so the Issue can be closed automatically upon merge, and the history shows in both. 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | # PSGrafana 4 | 5 | The PSGrafana module is a PowerShell wrapper around the Grafana API. Grafana uses this API internally for everything you do in the web interface. It made sense to create a wrapper such that you could bolt Grafana tasks to any automation pipelines one might have in their organizations. 6 | 7 | ## Status 8 | 9 | The module is currently in development, and as such expect rapid changes, specifically on the `develop` branch. The master branch will only contain code that has been deemed "working" and triggers the pipeline to publish new module versions. 10 | 11 | --- 12 | 13 | ## Contributing 14 | 15 | If you would like to help out, please target the `develop` branch when creating pull requests, otherwise the pipeline will have a bad time and we'll end up with stuff hitting the gallery too early. 16 | 17 | --- 18 | 19 | ## Currently available functions include: 20 | 21 | - Get-GrafanaConfig 22 | - Set-GrafanaConfig 23 | - Get-GrafanaDashboard 24 | - New-GrafanaDashboard 25 | - Set-GrafanaDashboard 26 | - Remove-GrafanaDashboard 27 | - Get-GrafanaServerHealth 28 | - Get-GrafanaApiKey 29 | - Get-GrafanaDatasource 30 | - Remove-GrafanaDatasource 31 | - Remove-GrafanaApiKey 32 | - New-GrafanaApiKey 33 | - New-GrafanaSnapshot 34 | - Get-GrafanaSnapshot 35 | - Remove-GrafanaSnapshot 36 | - Get-GrafanaAlert 37 | - Suspend-GrafanaAlert 38 | - New-GrafanaFolder 39 | - Get-GrafanaFolder 40 | - Remove-GrafanaFolder 41 | 42 | --- 43 | 44 | ## Installation 45 | 46 | #### Github: 47 | 48 | Option 1: 49 | 50 | Clone this repository. Import the psd1 file from the directory with `Import-module ./PSGrafana.psd1` or the full path to the psd1 file if outside the cloned directory. 51 | 52 | Option 2: 53 | 54 | Clone the repository somewhere in your $PSModulePath, and then run `Import-Module PSGrafana` 55 | 56 | Option 3: 57 | 58 | Download the zip archive and extract it on your machine and reference Option 1 or 2 above based on where you extract it too. 59 | 60 | #### Powershell Gallery 61 | 62 | This module is available via the Powershell Gallery. The latest released version is v0.0.4. 63 | 64 | To install simply run `Install-Module PSGrafana` 65 | 66 | _IMPORTANT NOTE REGARDING INSTALLATION:_ 67 | 68 | Upon first run, a configuration file will be generated for you by asking a series of questions. Namely: 69 | 70 | - What is your Grafana instance URL? 71 | - What is your Grafana instance API key? 72 | 73 | Once provided a Grafana.json file will be generated and placed in the Config directory of the module. All functions pull in this configuration in their `begin {}` blocks to reference the global $configuration variable. 74 | 75 | Currently, this config file does not survive updates from the Powershell Gallery. There is an issue created and I am working hard to resolve this in the most appropriate manner. 76 | 77 | --- 78 | 79 | ## Issues? 80 | 81 | Did you find a bug? Awesome! I wanna know about it. Please file an issue providing as much information as possible. 82 | Did you find a bug, _and_ fix the bug? Awesome! Thanks so much! Please file the detailed issue, and submit a PR for review. Be sure to add 'Fixes _issue\_number_' at the bottom of the PR notes so the Issue can be closed automatically upon merge, and the history shows in both. 83 | -------------------------------------------------------------------------------- /Test/Validation.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ProjectRoot = Resolve-Path "$PSScriptRoot\.." 2 | $ModuleRoot = Split-Path (Resolve-Path "$ProjectRoot\PSGrafana\*.psm1") 3 | $ModuleName = Split-Path $ModuleRoot -Leaf 4 | 5 | Describe "General project validation: $ModuleName" { 6 | BeforeAll { 7 | $FileSearch = @{ 8 | Path = $ProjectRoot 9 | Include = '*.ps1' 10 | Recurse = $true 11 | 12 | } 13 | $Scripts = Get-ChildItem @FileSearch 14 | } 15 | 16 | # TestCases are splatted to the script so we need hashtables 17 | $TestCases = $Scripts | ForEach-Object { @{File = $_} } 18 | It " should be valid powershell" -TestCases $TestCases { 19 | param($File) 20 | 21 | $File.FullName | Should -Exist 22 | 23 | $FileContents = Get-Content -Path $File.FullName -ErrorAction Stop 24 | $Errors = $null 25 | [System.Management.Automation.PSParser]::Tokenize($FileContents, [ref]$Errors) > $null 26 | $Errors.Count | Should -Be 0 27 | } 28 | 29 | If((Test-Path $ProjectRoot\PSGrafana\Config\*.json)){ 30 | It "'$ModuleName' can import cleanly" { 31 | {Import-Module (Join-Path $ModuleRoot "PSGrafana.psd1") -Force} | Should -Not -Throw 32 | } 33 | } 34 | } --------------------------------------------------------------------------------