Skip to content

Commit

Permalink
Initial Commit (#288)
Browse files Browse the repository at this point in the history
Adding four functions to help automate deploying SSRS projects based on the deployment setting from the SSRS project file.
  • Loading branch information
SQLvariant authored Oct 13, 2020
1 parent 8903c63 commit fc2257b
Show file tree
Hide file tree
Showing 30 changed files with 51,704 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
function Get-RsDeploymentConfig {
<#
.SYNOPSIS
This script retrieves a list of deployment configurations from a Reporting Services project file.
.DESCRIPTION
This function This script retrieves a list of deployment configurations from a Reporting Services project file for deployment to a Power BI Report Server.
.PARAMETER RsProjectFile
Specify the location of the SSRS project file whose deployment profiles should be fetched.
.PARAMETER ConfigurationToUse
Specify which configuration to use from the SSRS project file, if you already know it's name.
.EXAMPLE
Get-RsDeploymentConfig -RsProjectFile 'C:\Users\Aaron\source\repos\Finance\Financial Reports\SSRS_FR\SSRS_FR.rptproj'
Description
-----------
Retrieves all deployment profiles from the SSRS_FR.rptproj file and allows the user to choose which deployment configuration to use.
Then returns an object with all applicable settings from that deployment configuration.
.EXAMPLE
$RSConfig = Get-RsDeploymentConfig -RsProjectFile 'C:\Users\Aaron\source\repos\Financial Reports\SSRS_FR\SSRS_FR.rptproj'
Description
-----------
Retrieves all deployment profiles from the SSRS_FR.rptproj file and allows the user to choose which deployment configuration to use.
After the selection is made, the applicable settings are stored in the $RSConfig variable.
.EXAMPLE
$RSConfig = Get-RsDeploymentConfig -RsProjectFile 'C:\Users\Aaron\source\repos\Financial Reports\SSRS_FR\SSRS_FR.rptproj' -ConfigurationToUse Dev01 $RSConfig |
Add-Member -PassThru -MemberType NoteProperty -Name ReportPortal -Value 'http://localhost/PBIRSportal/'
$RSConfig | Deploy-RsProject
Retrieves all deployment settings for the 'Dev01' deployment configuration, adds a NoteProperty for the ReportPortal to deploy to,
and then deploys all the project files by calling Deploy-RsProject and passing in all the settings in the $RSConfig variable.
#>
param (
[Parameter(Mandatory = $true)]
[string]$RsProjectFile,

[Parameter(Mandatory = $false)]
[string]$ConfigurationToUse
)

if($ConfigurationToUse){
[XML]$rptproj = Get-Content $RsProjectFile
$Deployment = $rptproj.Project.PropertyGroup | where { $_.FullPath -eq $ConfigurationToUse }

$RSConfig = [pscustomobject]@{
FullPath = $Deployment.FullPath
OverwriteDatasets = $Deployment.OverwriteDatasets
OverwriteDataSources = $Deployment.OverwriteDataSources
TargetReportFolder = ($Deployment.TargetReportFolder).Trimend("/")
TargetDatasetFolder = ($Deployment.TargetDatasetFolder).Trimend("/")
TargetDatasourceFolder = ($Deployment.TargetDatasourceFolder).Trimend("/")
TargetReportPartFolder = ($Deployment.TargetReportPartFolder).Trimend("/")
TargetServerURL = $Deployment.TargetServerURL
RsProjectFolder = Split-Path -Path $RsProjectFile
}

return $RSConfig
}
else{[XML]$rptproj = Get-Content $RsProjectFile
$ConfigurationToUse = $rptproj.Project.PropertyGroup.FullPath | ogv -PassThru
$Deployment = $rptproj.Project.PropertyGroup | where { $_.FullPath -eq $ConfigurationToUse }

$RSConfig = [pscustomobject]@{
FullPath = $Deployment.FullPath
OverwriteDatasets = $Deployment.OverwriteDatasets
OverwriteDataSources = $Deployment.OverwriteDataSources
TargetReportFolder = ($Deployment.TargetReportFolder).Trimend("/")
TargetDatasetFolder = ($Deployment.TargetDatasetFolder).Trimend("/")
TargetDatasourceFolder = ($Deployment.TargetDatasourceFolder).Trimend("/")
TargetReportPartFolder = ($Deployment.TargetReportPartFolder).Trimend("/")
TargetServerURL = $Deployment.TargetServerURL
RsProjectFolder = Split-Path -Path $RsProjectFile
}

return $RSConfig
}
}
159 changes: 159 additions & 0 deletions ReportingServicesTools/Functions/CatalogItems/Publish-RsProject.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
function Publish-RsProject
{
<#
.SYNOPSIS
This script deploys a Reporting Services project to a Power BI Report Server.
.DESCRIPTION
This function deploys a full SSRS project to a Power BI Report Server.
.PARAMETER ProjectFolder
Specify the location of the SSRS project file whose deployment profiles should be fetched.
.EXAMPLE
Get-RsDeploymentConfig -ProjectFile 'C:\Users\Aaron\source\repos\Finance\Financial Reports\SSRS_FR\SSRS_FR.rptproj' |
Add-Member -PassThru -MemberType NoteProperty -Name ReportPortal -Value 'http://localhost/PBIRSportal/' |
Publish-RsProject
Description
-----------
Get-RsDeploymentConfig prompts the user to select which deployment configuration to use from
the 'C:\Users\Aaron\source\repos\Finance\Financial Reports\SSRS_FR\SSRS_FR.rptproj' project file. These settings
are piped to the Add-Member where the ReportPortal property is added and set to 'http://localhost/PBIRSportal/'.
The settings are then piped to the Publish-RsProject function, which deploys all project files using all applicable
settings from the deployment configuration chosen.
.EXAMPLE
$RSConfig = Get-RsDeploymentConfig -RsProjectFile 'C:\Users\Aaron\source\repos\Financial Reports\SSRS_FR\SSRS_FR.rptproj' -ConfigurationToUse Dev01
Add-Member -PassThru -MemberType NoteProperty -Name ReportPortal -Value 'http://localhost/PBIRSportal/'
$RSConfig | Publish-RsProject
Description
-----------
Retrieves all deployment settings for the 'Dev01' deployment configuration, adds a NoteProperty for the ReportPortal to
deploy to, and then deploys all the project files by calling Publish-RsProject and passing in all the settings in
the $RSConfig variable.
.EXAMPLE
Publish-RsProject -TargetServerURL 'http://localhost/PBIRServer/' -ReportPortal 'http://localhost/PBIRSportal/' -TargetReportFolder /Finance -TargetDatasourceFolder '/Finance/Data Sources' -TargetDatasetFolder /Finance/DataSets -RsProjectFolder 'C:\Users\Aaron\source\repos\Financial Reports\SSRS_FR\'
Description
-----------
Deploys the project files found in the 'C:\Users\Aaron\source\repos\Financial Reports\SSRS_FR\' to the target locations
specified in the parameters list. Use this option when you want to deploy to a location not already listed in
the .rptproj project file.
#>
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
param (
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
[string]$RsProjectFolder,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$TargetServerURL,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$TargetReportFolder,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$TargetDatasourceFolder,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$TargetDatasetFolder,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$TargetReportPartFolder,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$OverwriteDatasets,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$OverwriteDataSources,

[Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[string]$FullPath,

[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
[string]$ReportPortal
)

Write-Host "`$RsProjectFolder = '$RsProjectFolder' being used is
This deployment is going to happen using the following settings...
"
$RSConfig | FL

<# RsFolder Structure
Make sure all the folders needed already exist with the following code. #>
Write-Host "
Beginning deployment.
Building folder structures...
"

$TargetReportFolder, $TargetDatasourceFolder, $TargetDatasetFolder |
sort -Unique |
foreach {
MakeDeploymentFolders -RsFolder $_ -ReportPortal $ReportPortal
}

<# Deploy Data Sources #>
Write-Host "
Deploying Data Sources to $($TargetDatasourceFolder)...
"
foreach($RDS in dir -Path $RsProjectFolder -Filter *.rds)
{
try{ Write-Verbose "Checking for $TargetDatasourceFolder/$($_.BaseName)"
Get-RsRestItem -ReportPortalUri $ReportPortal -RsItem "$TargetDatasourceFolder/$($RDS.BaseName)" | ft -AutoSize
}
catch{ Write-Verbose 'Did not find Data Source'
Write-RsRestCatalogItem -Path "$RsProjectFolder\$($RDS.Name)" -ReportPortalUri $ReportPortal -RsFolder $TargetDatasourceFolder
}
}

<# Deploy Data Sets & set their Data Source References. #>
Write-Host "
Deploying DataSets to $TargetDatasetFolder...
"
dir -Path $RsProjectFolder -Filter *.rsd |
foreach{
[XML]$dsetref = Get-Content "$RsProjectFolder\$($_.Name)"
$DataSetQuery = $dsetref.SharedDataSet.DataSet.Query

$DSetConfig = [pscustomobject]@{
DataSourceReference = $dsetref.SharedDataSet.DataSet.Query.DataSourceReference
CommandText = $dsetref.SharedDataSet.DataSet.Query.CommandText
CommandType = $dsetref.SharedDataSet.DataSet.Query.CommandType
DataSetParameters = $dsetref.SharedDataSet.DataSet.Query.DataSetParameters
}

Write-RsRestCatalogItem -Path "$RsProjectFolder\$($_.Name)" -ReportPortalUri $ReportPortal -RsFolder $TargetDatasetFolder -Overwrite
Set-RsDataSourceReference -ReportServerUri $TargetServerURL -Path "$TargetDatasetFolder/$($_.BaseName)" -DataSourceName DataSetDataSource -DataSourcePath "$($TargetDatasourceFolder)/$($DSetConfig.DataSourceReference)"
}

<# Deploy the Reports #>
Write-Host "Deploying the report files to $TargetReportFolder...
"
dir -Path $RsProjectFolder -Filter *.rdl |
foreach{
$ReportName=$_.BaseName
Write-RsCatalogItem -Path "$RsProjectFolder\$($_.Name)" -ReportServerUri $TargetServerURL -RsFolder $TargetReportFolder -Overwrite
"$($_.BaseName)";
Get-RsRestItemDataSource -ReportPortalUri $ReportPortal -RsItem "$TargetReportFolder/$ReportName" |
where {$_.IsReference -eq $true} |
foreach{
Set-RsDataSourceReference -ReportServerUri $TargetServerURL -Path "$TargetReportFolder/$ReportName" -DataSourceName $_.Name -DataSourcePath "$($TargetDatasourceFolder)/$($_.Name)"
}
}

<# Now read in the DataSet References directly from the report files and set them on the server #>
if($TargetDatasetFolder -ne $TargetReportFolder -and (Get-RsRestFolderContent -ReportPortalUri $ReportPortal -RsFolder $TargetDatasetFolder).Count -gt 0){
$Reports = dir -Path $RsProjectFolder -Filter *.rdl

foreach($Report in $Reports)
{
[XML]$ReportDSetRef = Get-Content $Report.FullName
foreach($SDS in $ReportDSetRef.Report.DataSets.DataSet){
Set-RsDataSetReference -ReportServerUri $TargetServerURL -Path "$TargetReportFolder/$($Report.BaseName)" -DataSetName $SDS.Name -DataSetPath "$TargetDatasetFolder/$($SDS.SharedDataSet.SharedDataSetReference)"
}
}
}

}
18 changes: 18 additions & 0 deletions ReportingServicesTools/Functions/Common/MakeDeploymentFolders.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function MakeDeploymentFolders {
param($RsFolder,$ReportPortal)
$tree=$null
$tree
$Base='/'
($RsFolder.substring(1,$RsFolder.length-1)).split('/') | foreach{
$Folder = $_
$tree += "/"+$Folder
try{
Get-RsRestItem -ReportPortalUri $ReportPortal -RsItem $tree| ft -AutoSize
}
catch{
Write-Warning "Folder $tree does not exist";
New-RsRestFolder -ReportPortalUri $ReportPortal -RsFolder $Base -FolderName $Folder -Verbose
}
$Base=$tree
}
}
2 changes: 2 additions & 0 deletions ReportingServicesTools/ReportingServicesTools.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
'Export-RsSubscriptionXml',
'Get-RsCatalogItemRole',
'Get-RsDataSource',
'Get-RsDeploymentConfig',
'Get-RsFolderContent',
'Get-RsRestFolderContent',
'Get-RsItemDataSource',
Expand All @@ -93,6 +94,7 @@
'Out-RsFolderContent',
'Out-RsRestCatalogItem',
'Out-RsRestFolderContent',
'Publish-RsProject',
'Register-RsPowerBI',
'Remove-RsCatalogItem',
'Remove-RsRestFolder',
Expand Down
21 changes: 21 additions & 0 deletions Tests/CatalogItems/Get-RsDeploymentConfig.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

Describe "Get-RsDeploymentConfig" {
$RSConfig = Get-RsDeploymentConfig -RsProjectFile "$($PSScriptRoot)\TestProjects\SQLServerPerformanceDashboardReportingSolution\SQL Server Performance Dashboard\SQL Server Performance Dashboard.rptproj" -ConfigurationToUse Release

Write-Verbose "$RSConfig.TargetServerURL"
Write-Verbose "$RSConfig.RsProjectFolder"

Context "Get the DeploymentConfig of a ReportServer project file using ConfigurationToUse parameter"{
# Create a folder
# Test if the config was found
It "Should verify TargetServerURL matches" {
$RSConfig.TargetServerURL | Should Be 'http://localhost/reportserver'
}

# Test if the folder can be found
It "Should verify a config was retrieved" {
@($RSConfig).Count | Should Be 1
}

}
}
31 changes: 31 additions & 0 deletions Tests/CatalogItems/Publish-RsProject.Test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
$reportPortalUri = if ($env:PesterPortalUrl -eq $null) { 'http://localhost/reports' } else { $env:PesterPortalUrl }

Describe "Publish-RsProject" {
Context "Deploy an entire SSRS Project by getting the DeploymentConfig of a ReportServer project file using ConfigurationToUse parameter"{
# Create a folder
$RSConfig = Get-RsDeploymentConfig -RsProjectFile "$($PSScriptRoot)\TestProjects\SQLServerPerformanceDashboardReportingSolution\SQL Server Performance Dashboard\SQL Server Performance Dashboard.rptproj" -ConfigurationToUse Release |
Add-Member -PassThru -MemberType NoteProperty -Name ReportPortal -Value $reportPortalUri

# Test if the config was retrieved
It "Should verify a config was retrieved" {
@($RSConfig).Count | Should Be 1
}

# Test if the TargetServerURL in the config was found
It "Should verify TargetServerURL matches" {
$RSConfig.TargetServerURL | Should Be 'http://localhost/reportserver'
}

$RSConfig | Publish-RsProject
$CatalogList = Get-RsRestFolderContent -reportPortalUri $RSConfig.ReportPortal -RsFolder '/SQL Server Performance Dashboard' -Recurse
$folderCount = ($CatalogList | measure).Count
It "Should find at least 1 folder" {
$folderCount | Should Be 22
}
# Removing folders used for testing
Remove-RsCatalogItem -RsFolder $RSConfig.TargetReportFolder -Confirm:$false
Remove-RsCatalogItem -RsFolder $RSConfig.TargetDatasetFolder -Confirm:$false
Remove-RsCatalogItem -RsFolder $RSConfig.TargetDatasourceFolder -Confirm:$false

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{F14B399A-7131-4C87-9E4B-1186C45EF12D}") = "SQL Server Performance Dashboard", "SQL Server Performance Dashboard\SQL Server Performance Dashboard.rptproj", "{280F4418-C6F5-4763-8CA4-63AD770AFB58}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Default = Debug|Default
DebugLocal|Default = DebugLocal|Default
Release|Default = Release|Default
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.Debug|Default.ActiveCfg = Debug
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.Debug|Default.Build.0 = Debug
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.Debug|Default.Deploy.0 = Debug
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.DebugLocal|Default.ActiveCfg = DebugLocal
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.DebugLocal|Default.Build.0 = DebugLocal
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.Release|Default.ActiveCfg = Release
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.Release|Default.Build.0 = Release
{280F4418-C6F5-4763-8CA4-63AD770AFB58}.Release|Default.Deploy.0 = Release
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Loading

0 comments on commit fc2257b

Please sign in to comment.