Public/Tasks/Invoke-InstallSolrTask.ps1

#Requires -Modules SitecoreInstallFramework, SitecoreFundamentals
#Requires -RunAsAdministrator

Set-StrictMode -Version Latest

Write-Verbose "Loading $($MyInvocation.MyCommand.Path)"

Function Invoke-InstallSolrTask
{
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidDefaultValueSwitchParameter", "")]
    [CmdletBinding(SupportsShouldProcess = $true)]
    Param(
        [string]$SolrVersion = "6.6.2",
        [string]$SolrInstallPath = "$($env:SystemDrive)\solr",
        [int]$SolrPort = 8983,
        [string]$SolrHost = "solr",
        [bool]$SolrUseSSL = $true,
        [string]$SolrService = "solr",
        [string]$NssmVersion = "2.24",
        [string]$TaskName = "InstallSolr"
    )

    Set-PSDebug -Strict

    # $sifHelperModule = (Get-Module SifHelper)
    # Write-TaskInfo "SifHelper: $sifHelperModule" -Tag SolrDebug
    # $sifHelperPath = Split-Path -Parent ($sifHelperModule.Path)
    # Write-TaskInfo "SifHelper: $sifHelperModule" -Tag SolrDebug
    # $utilities = Join-Path -Path $sifHelperPath -ChildPath 'Private\Utilities.psm1'
    # Write-TaskInfo "SifHelper: $utilities" -Tag SolrDebug
    # Import-Module $utilities -Verbose

    $solrName = "solr-$SolrVersion"
    $solrRoot = Join-Path $SolrInstallPath $solrName
    $nssmName = "nssm-$NssmVersion"
    $nssmRoot = Join-Path $SolrInstallPath $nssmName
    $solrPackage = "http://archive.apache.org/dist/lucene/solr/$SolrVersion/$solrName.zip"
    $nssmPackage = "http://nssm.cc/release/$nssmName.zip"


    # AssertElevated

    if ($PSCmdlet.ShouldProcess($solrPackage)) {
        # download & extract the nssm archive to the right folder
        Invoke-DownloadAndUnpackTask -sourceUri $solrPackage -destinationPath $SolrInstallPath -Clean:$false
    }

    if ($PSCmdlet.ShouldProcess($nssmPackage)) {
        # download & extract the nssm archive to the right folder
        Invoke-DownloadAndUnpackTask -sourceUri $nssmPackage -destinationPath $SolrInstallPath -Clean:$false
    }


    function Get-LocalRootCert {
        param(
            [string]$friendlyName
        )

        $returnCert = Get-ChildItem Cert:\LocalMachine\Root | Where-Object FriendlyName -eq "$friendlyName"

        return $returnCert
    }

    # if we're using HTTP
    if(!$SolrUseSSL)
    {
        # Update solr cfg to use right host name
        if(!(Test-Path -Path "$solrRoot\bin\solr.in.cmd.old"))
        {
            Write-Verbose "Rewriting solr config"

            if ($PSCmdlet.ShouldProcess($SolrUseSSL)) {

                $cfg = Get-Content "$solrRoot\bin\solr.in.cmd"
                Rename-Item "$solrRoot\bin\solr.in.cmd" "$solrRoot\bin\solr.in.cmd.old"
                $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_HOST=192.168.1.1", "set SOLR_HOST=$SolrHost" }
                $newCfg | Set-Content "$solrRoot\bin\solr.in.cmd"
            }
        }
    }


    #region "Certificate Installation"

    # if we're using HTTPS
    if($SolrUseSSL)
    {
        # Generate SSL cert
        $existingCert = Get-LocalRootCert "$SolrHost"

        if(!($existingCert))
        {
            Write-Verbose "Creating & trusting an new SSL Cert for $SolrHost"

            if ($PSCmdlet.ShouldProcess($existingCert)) {

                New-SelfSignedCert -Name $SolrHost -FriendlyName $SolrHost -DnsName $SolrHost -CertStoreLocation "Cert:\LocalMachine\My" -Verbose

                Write-TaskInfo "Created certificate $SolrHost." -Tag Cert -TaskName $TaskName
            }
        } else {
            Write-TaskInfo "Certificate $SolrHost exists" -Tag Cert -TaskName $TaskName
        }

        [string]$solrSslKeyStore = Join-Path $solrRoot 'server\etc\solr-ssl.keystore.pfx'

        # export the cert to pfx using solr's default password
        if(!(Test-Path -Path $solrSslKeyStore))
        {
            Write-Verbose "Exporting cert for Solr to use"

            $cert = Get-LocalRootCert "$SolrHost"

            $certPwd = ConvertTo-SecureString -String "secret" -Force -AsPlainText

            if ($PSCmdlet.ShouldProcess($cert)) {
                $cert | Export-PfxCertificate -FilePath $solrSslKeyStore -Password $certpwd | Out-Null
            }

            Write-TaskInfo "Exported cert for Solr to use" -Tag Cert -TaskName $TaskName
        }

        # Update solr cfg to use keystore & right host name
        if(!(Test-Path -Path "$solrRoot\bin\solr.in.cmd.old"))
        {
            Write-Verbose "Rewriting solr config"

            if ($PSCmdlet.ShouldProcess($solrRoot)) {
                $cfg = Get-Content "$solrRoot\bin\solr.in.cmd"

                Rename-Item "$solrRoot\bin\solr.in.cmd" "$solrRoot\bin\solr.in.cmd.old"
                $newCfg = $cfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_KEY_STORE=$solrSslKeyStore" }
                $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_KEY_STORE_PASSWORD=secret", "set SOLR_SSL_KEY_STORE_PASSWORD=secret" }
                $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_TRUST_STORE=$solrSslKeyStore" }
                $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_TRUST_STORE_PASSWORD=secret", "set SOLR_SSL_TRUST_STORE_PASSWORD=secret" }
                $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_HOST=192.168.1.1", "set SOLR_HOST=$SolrHost" }
                $newCfg | Set-Content "$solrRoot\bin\solr.in.cmd"
            }

            Write-TaskInfo "Updated solr cfg to use keystore & set SOLR_HOST=$SolrHost" -Tag Cert -TaskName $TaskName

        }
    }
    #endregion

    # install the service & runs
    $svc = Get-Service "$SolrService" -ErrorAction SilentlyContinue

    if(!($svc))
    {
        Write-Verbose "Installing Solr service"
        if ($PSCmdlet.ShouldProcess($SolrService)) {
            & "$nssmRoot\win64\nssm.exe" install "$SolrService" "$solrRoot\bin\solr.cmd" "-f" "-p $SolrPort"
            $svc = Get-Service "$SolrService" -ErrorAction SilentlyContinue
        }
        Write-TaskInfo "Installed service $SolrService" -Tag Service -TaskName $TaskName
    } else {
        Write-Warning "Service $SolrService already exists."
    }

    if ($PSCmdlet.ShouldProcess($svc)) {
        if($svc.Status -ne "Running")
        {
            Write-Verbose "Starting Solr service"
            Start-Service "$SolrService"
            Write-TaskInfo "Started service $SolrService" -Tag Service -TaskName $TaskName
        } else {
            Write-Warning "Service $SolrService is already running."
        }
    }

    Write-TaskInfo "Installed Solr" -Tag Solr -TaskName $TaskName

    if ($PSCmdlet.ShouldProcess($solrPackage) -and $PSCmdlet.ShouldProcess($nssmPackage)) {
        Invoke-EnsurePathTask -Clean $solrPackage,$nssmPackage -ErrorAction:SilentlyContinue
    }
}

Register-SitecoreInstallExtension -Command Invoke-InstallSolrTask -As InstallSolr -Type Task -Force

Write-Verbose "Loaded $($MyInvocation.MyCommand.Path)"