Sitecore.Automation.Framework.psm1

$ErrorActionPreference = "Stop"
Set-ExecutionPolicy Bypass -Scope Process -Force

function GetConfig {
    [CmdletBinding()]
    Param
    (
        [string]$Config
    )

    if (!(Test-Path $Config)) {
        throw "Please, provide Configuration JSON file."
    }

    return (Get-Content -Raw -Path $Config) -replace '// .*' | Out-String | ConvertFrom-Json
}

function EnsureRunAsAdmin {
    ## Verify elevated
    ## https://superuser.com/questions/749243/detect-if-powershell-is-running-as-administrator
    $elevated = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
    if ($elevated -eq $false) {
        throw "In order to use SAF, please run this script elevated. If you are using Visual Studio Plug-in, please run Visual Studio as Administrator."
    }
}

function WriteWelcomeMessage {
    Write-Output "`n`n------------------------------------------------------"
    Write-Output "--- Welcome to Sitecore Automation Framework (SAF) ---"
    Write-Output "------------------------------------------------------`n`n"
}

function WriteFinishedMessage {
    Write-Output "`n`n------------------------------------------------------"
    Write-Output "---------- SAF has finished its job. Enjoy! ----------"
    Write-Output "------------------------------------------------------`n`n"
}

function Initialize {
    [CmdletBinding()]
    Param
    (
        [string]$Config
    )

    Write-Output "SAF initialization is running, please wait..."

    EnsureRunAsAdmin

    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\ThirdPartyDependencies-Module.psm1" -Global -Force

    ConfigureChoco

    $safConfigJSON = $null
    if (![string]::IsNullOrEmpty($Config)) {
        $safConfigJSON = GetConfig -Config $Config
        Split-Path $Config | Set-Location
    }

    . $PSScriptRoot\SAFParams.ps1 -Configuration $safConfigJSON

    $modules = @(Get-ChildItem -Path $PSScriptRoot\Core\* -Include *.psm1 -Recurse -Force)
    foreach ($module in $modules) {
        if ($module.FullName.Contains('Utils-Module')) { continue }
        if ($module.FullName.Contains('ThirdPartyDependencies-Module')) { continue }
        Import-Module $module.FullName -Global -Force
    }
}

function Install-Sitecore {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    InstallSitecore -Force:$Force
    WriteFinishedMessage
}

function Install-SitecorePackages {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    & "$PSScriptRoot\Pipelines\Steps\Install\OnPrem\Sitecore\Install-SitecorePackages.ps1"
    WriteFinishedMessage
}

function Uninstall-Sitecore {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    UninstallSitecore -Force:$Force
    WriteFinishedMessage
}

function Install-Solr {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )
    
    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    InstallSolr -Force:$Force
    WriteFinishedMessage
}

function New-SolrConfigSets {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )
    
    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    GenerateNewSolrConfigSets -Force:$Force
    WriteFinishedMessage
}

function New-SolrCoresViaHTTP {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )
    
    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    CreateNewSolrCoresViaHTTP -Force:$Force
    WriteFinishedMessage
}

function Uninstall-Solr {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    UninstallSolr -Force:$Force
    WriteFinishedMessage
}
 
function New-SSLCerts {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    NewSSLCerts -Force:$Force
    WriteFinishedMessage
}

function Clear-SAFCache {
    WriteWelcomeMessage
    Initialize
    Write-Output "Clear cache started..."
    RemoveTemp
    Write-Output "Cache is cleared."
    WriteFinishedMessage
}

function New-SolrRebuildCores {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    & "$PSScriptRoot\Pipelines\Steps\Install\OnPrem\Solr\Create-RebuildCores.ps1"
    & "$PSScriptRoot\Pipelines\Steps\Install\OnPrem\Solr\Add-SolrCoresEnvConfig.ps1"
    WriteFinishedMessage
}

function New-SolrCustomCores {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    ImportSIF
    $version = $SAFConfiguration.sitecore.version
    $majorMinorOnly = $version.Substring(0, ($version.LastIndexOf('.')))
    & "$PSScriptRoot\Pipelines\Steps\Install\OnPrem\Sitecore\XM\Solr\$majorMinorOnly\Create-CustomSolrCores.ps1"
    & "$PSScriptRoot\Pipelines\Steps\Install\OnPrem\Solr\Add-SolrCoresEnvConfig.ps1"
    WriteFinishedMessage
}

function Initialize-CakeBuild {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage
    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\CakeBuild-Module.psm1" -Global -Force
    InitializeCakeBuild -CakeBuildFile $Config
    SaveCakeBuildFilePath -CakeBuildFile $Config
    WriteFinishedMessage
    Start-Sleep -s 5
}

function Publish-WebProject {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage

    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\CakeBuild-Module.psm1" -Global -Force

    $values = $Config.Split('#')
    $projFile = $values[0]
    $slnFile = $values[1]

    $projDir = Split-Path "$projFile"
    $cakeBuildFile = GetCakeBuildFilePath -CurrentDirectory "$projDir"

    if ($null -eq $cakeBuildFile) {
        Write-Warning "SAF was not able to find the Cake build file."
        Write-Warning "Please, add 'cake.build' file to your solution."
        Write-Warning "If you already have added 'cake.build' file, right click on it and run 'SAF -> Initialize Cake Build'."
    }
    else {
        & "$cakeBuildFile" -Script "$cakeBuildFile".Replace(".ps1", ".cake") -Target "001-Publish-Project" --settings_skippackageversioncheck=true --settings_skipverification=true --current_project=$projFile --current_solution_file=$slnFile
        if ($LASTEXITCODE -eq 0) {
            WriteFinishedMessage
            Start-Sleep -s 5
        }
        else {
            Start-Sleep -s 5
            exit $LASTEXITCODE
        }
    }
}

function Publish-File {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    WriteWelcomeMessage

    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\CakeBuild-Module.psm1" -Global -Force

    $values = $Config.Split('#')
    $projFile = $values[0]
    $slnFile = $values[1]

    $projDir = Split-Path "$projFile"
    $cakeBuildFile = GetCakeBuildFilePath -CurrentDirectory "$projDir"

    if ($null -eq $cakeBuildFile) {
        Write-Warning "SAF was not able to find the Cake build file."
        Write-Warning "Please, add 'cake.build' file to your solution."
        Write-Warning "If you already have added 'cake.build' file, right click on it and run 'SAF -> Initialize Cake Build'."
    }
    else {
        & "$cakeBuildFile" -Script "$cakeBuildFile".Replace(".ps1", ".cake") -Target "002-Publish-File" --settings_skippackageversioncheck=true --settings_skipverification=true --current_file=$projFile --current_solution_file=$slnFile
        
        if ($LASTEXITCODE -eq 0) {
            WriteFinishedMessage
            Start-Sleep -s 5
        }
        else {
            Start-Sleep -s 5
            exit $LASTEXITCODE
        }
    }
}

function Publish-AllProjects {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\CakeBuild-Module.psm1" -Global -Force

    $solutionDir = Split-Path "$Config"
    $cakeBuildFile = GetCakeBuildFilePath -CurrentDirectory "$solutionDir"

    if ($null -eq $cakeBuildFile) {
        Write-Warning "SAF was not able to find the Cake build file."
        Write-Warning "Please, add 'cake.build' file to your solution."
        Write-Warning "If you already have added 'cake.build' file, right click on it and run 'SAF -> Initialize Cake Build'."
    }
    else {
        & "$cakeBuildFile" -Script "$cakeBuildFile".Replace(".ps1", ".cake") -Target "003-Publish-All-Projects" --settings_skippackageversioncheck=true --settings_skipverification=true --current_solution_file=$Config
        Start-Sleep -s 5
        exit $LASTEXITCODE
    }
}

#TODO Refactor after Publish-All-Projects changes
function Publish-Solution {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )

    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\CakeBuild-Module.psm1" -Global -Force
    $values = $Config.Split('#')
    $repoPath = $values[0]
    $publishDir = $values[1]
    $buildConfiguration = $values[2]

    $cakeBuildFile = GetCakeBuildFilePath -CurrentDirectory "$repoPath"

    if ($null -eq $cakeBuildFile) {
        Write-Warning "SAF was not able to find the Cake build file."
        Write-Warning "Please, add 'cake.build' file to your solution."
        Write-Warning "If you already have added 'cake.build' file, right click on it and run 'SAF -> Initialize Cake Build'."
    }
    else {
        & "$cakeBuildFile" -Script "$cakeBuildFile".Replace(".ps1", ".cake") -Target "003-Publish-All-Projects" --settings_skippackageversioncheck=true --settings_skipverification=true --publish_dir=$publishDir --build_configuration=$buildConfiguration
        Start-Sleep -s 5
        exit $LASTEXITCODE
    }
}

function Initialize-Deployer {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )
    
    WriteWelcomeMessage
    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\Deployer-Module.psm1" -Global -Force
    InitializeDeployer -SolutionFile $Config
    WriteFinishedMessage
}

function New-DeploymentPackage {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )
    
    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\CakeBuild-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\Deployer-Module.psm1" -Global -Force
    NewDeploymentPackage -SolutionFile $Config
}

function New-DeploymentTag {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config,
        [switch]$Force
    )
    
    Import-Module "$PSScriptRoot\Core\Utils-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\CakeBuild-Module.psm1" -Global -Force
    Import-Module "$PSScriptRoot\Core\Deployer-Module.psm1" -Global -Force
    NewDeploymentTag -SolutionFile $Config
}

# Helper functions
function Import-SSLCert {
    [CmdletBinding()]
    Param
    (
        [string]$PfxName,
        [string]$Password,
        [switch]$Root
    )

    ImportCert -PfxName $PfxName -Password $Password -Root:$Root 
}

function Set-AppPoolAccessToSSLCert {
    [CmdletBinding()]
    Param
    (
        [string]$PfxName,
        [string]$AppPoolName
    )

    SetAppPoolAccessToSSLCert -SSLCertName $PfxName -AppPoolName $AppPoolName
}

function Set-AppPoolAccessToDirectory {
    [CmdletBinding()]
    Param
    (
        [string]$Directory,
        [string]$AppPoolName
    )

    SetDirectoryAccess -Directory $Directory -AppPoolName $AppPoolName
}

function Remove-Database {
    [CmdletBinding()]
    Param
    (
        [string]$SqlServer,
        [string]$Database,
        [string]$AdminUsername,
        [string]$AdminPassword
    )

    $dbs = ("$Database")
    DeleteDatabases -SqlServer $SqlServer -Databases $dbs -Username $AdminUsername -Password $AdminPassword
}

function Add-Database {
    [CmdletBinding()]
    Param
    (
        [string]$SqlServer,
        [string]$AdminUsername,
        [string]$AdminPassword,
        [string]$LocalDbUsername,
        [string]$LocalDbPassword,
        [string]$DbName,
        [string]$Dacpac
    )

    DeployDacpac -SqlServer $SqlServer -Username $AdminUsername -Password $AdminPassword -LocalDbUsername $LocalDbUsername -LocalDbPassword $LocalDbPassword -Dacpac $Dacpac -TargetDatabaseName $DbName
}

function Add-CustomDatabases {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Config
    )

    WriteWelcomeMessage
    Initialize -Config $Config
    & "$PSScriptRoot\Pipelines\Steps\SQL\Deploy-CustomDatabases.ps1"
    WriteFinishedMessage
}

function Get-SAFConfig {
    [CmdletBinding()]
    Param
    (
        [string]$Config
    )
    
    return GetConfig -Config $Config
}

Export-ModuleMember -Function "Install-Sitecore"
Export-ModuleMember -Function "Install-SitecorePackages"
Export-ModuleMember -Function "Uninstall-Sitecore"
Export-ModuleMember -Function "Install-Solr"
Export-ModuleMember -Function "New-SolrConfigSets"
Export-ModuleMember -Function "New-SolrCoresViaHTTP"
Export-ModuleMember -Function "Uninstall-Solr"
Export-ModuleMember -Function "New-SSLCerts"
Export-ModuleMember -Function "Clear-SAFCache"
Export-ModuleMember -Function "New-SolrCustomCores"
Export-ModuleMember -Function "New-SolrRebuildCores"
Export-ModuleMember -Function "Import-SSLCert"
Export-ModuleMember -Function "Set-AppPoolAccessToSSLCert"
Export-ModuleMember -Function "Remove-Database"
Export-ModuleMember -Function "Add-Database"
Export-ModuleMember -Function "Add-CustomDatabases"
Export-ModuleMember -Function "Get-SAFConfig"
Export-ModuleMember -Function "Set-AppPoolAccessToDirectory"
Export-ModuleMember -Function "Initialize-CakeBuild"
Export-ModuleMember -Function "Publish-WebProject"
Export-ModuleMember -Function "Publish-File"
Export-ModuleMember -Function "Publish-Solution"
Export-ModuleMember -Function "Initialize-Deployer"
Export-ModuleMember -Function "New-DeploymentPackage"
Export-ModuleMember -Function "New-DeploymentTag"
Export-ModuleMember -Function "Publish-AllProjects"