Wednesday, September 16, 2015

DevOps and PowerShell : Automating SonarQube installation – Part 3

This is the 3rd post of the automation SonarQube installation series. In the previous parts we’ve seen how to setup the infrastructure for SonarQube and configure SQL server for our use. In this part I’ll show how to configure firewall ports, update the SonarQube configurations based on our setup and finally start the SonarQube service on our machine.

Configure firewall rules.

By default SonarQube runs on port 9000. To make sure that this port is accessible from outside, we need to open the port to allow incoming connections to the port. A new firewall rule can be added by using the method

function New-FirewallRule
{
       [CmdletBinding()]
       param
       (
              [Parameter(Mandatory=$true, Position=0)]
              [ValidateNotNullOrEmpty()]
              [string] $Name,

              [Parameter(Mandatory=$true, Position=1)]
              [ValidateNotNullOrEmpty()]
              [string] $TCPPorts,

              [Parameter(Mandatory=$false, Position=2)]
              [string] $ApplicationName,
             
              [Parameter(Mandatory=$false, Position=3)]
              [string] $ServiceName
       )

       $firewall = New-Object -ComObject hnetcfg.fwpolicy2

       if( ($firewall.Rules | select -expand localports |? {$_ -eq $TCPPorts }) -eq $null)
       {
              "Adding firewall rule to open ports $TCPPorts" | Write-Verbose
              $rule = New-Object -ComObject HNetCfg.FWRule
       
              $rule.Name = $name
              if (-not ([string]::IsNullOrEmpty($ApplicationName)))
              {
                     $rule.ApplicationName = $ApplicationName
              }
              if (-not ([string]::IsNullOrEmpty($ServiceName)))
              {
                     $rule.serviceName = $ServiceName
              }
              $rule.Protocol = 6 #NET_FW_IP_PROTOCOL_TCP
              $rule.LocalPorts = $TCPPorts
              $rule.Enabled = $true
              $rule.Grouping = "@firewallapi.dll,-23255"
              $rule.Profiles = 7 # all
              $rule.Action = 1 # NET_FW_ACTION_ALLOW
              $rule.EdgeTraversal = $false
   
              $firewall.Rules.Add($rule)
       }
    else
       {
              "The firewall rule for $TCPPorts already exists"  | Write-Verbose
       }
}

#Open Firewall ports
New-FirewallRule -Name "Allow SonarQube port 9000"  -TCPPorts "9000" -Verbose

Updating the SonarQube configuration.

Now we are ready to configure SonarQube to use our settings. The configuration for SonarQube is available in the conf folder of the SonarQube installation as the sonar.properties file. In this file we need to first uncomment out the sonar.jdbc.url line and set the values for the connection to the sql server database. We'll also need to update the jdbc username and password for the database login. I've made use of the Get-Content and Set-Content cmdlets to do this

function Set-SonarDbProperties
{
       [CmdletBinding()]
       param
       (
              [Parameter(Mandatory=$false, Position=0)]
              [ValidateScript({Test-Path $_})]
              [string] $SonarSource = "C:\SonarQube\sonarqube-5.1.2",

              [Parameter(Mandatory=$false, Position=1)]
              [string] $SqlServerName = "localhost",

              [Parameter(Mandatory=$false, Position=2)]
              [string] $DbName = "sonar",
             
              [Parameter(Mandatory=$true, Position=3)]
              [ValidateNotNullOrEmpty()]
              [string] $SqlLogin,

              [Parameter(Mandatory=$true, Position=4)]
              [ValidateNotNullOrEmpty()]
              [string] $SqlPassword
       )


       if(-not(Join-Path $SonarSource "conf\sonar.properties" | Test-Path))
       {
              throw "Failed to find a valid sonarqube configuration file at source location $SonarSource"
       }

       "Updating JDBC url" | Write-Verbose
       $configurationFilePath = Join-Path $SonarSource "conf\sonar.properties"
       (Get-Content $configurationFilePath).Replace("#sonar.jdbc.url=jdbc:jtds:sqlserver://localhost/sonar;SelectMethod=Cursor", "sonar.jdbc.url=jdbc:jtds:sqlserver://$SqlServerName/$DbName;SelectMethod=Cursor") | Set-Content $configurationFilePath

       "Updating JDBC username" | Write-Verbose
       (Get-Content $configurationFilePath).Replace("#sonar.jdbc.username=sonar", "sonar.jdbc.username=$SqlLogin") | Set-Content $configurationFilePath
      
       "Updating JDBC password" | Write-Verbose
       (Get-Content $configurationFilePath).Replace("#sonar.jdbc.password=sonar", "sonar.jdbc.password=$SqlPassword") | Set-Content $configurationFilePath
}

#Set JDBC URL, Username and Password
Set-SonarDbProperties -SonarSource (Join-Path $installFolder sonarqube-5.1.2) -SqlLogin "sonaruser" -SqlPassword "SonarPass@12" -Verbose

Starting the SonarQube service

The last step is to install SonarQube as a service. The installation is assisted by a .bat file provided as part of the SonarQube donwload. The .bat file can be found at the bin folder in the respective configuration.
Executing this .bat file will install the SonarQube service on the machine.

function Install-SonarQubeService
{
       [CmdletBinding()]
       param
       (
              [Parameter(Mandatory=$false, Position=0)]
              [ValidateScript({Test-Path $_})]
              [string] $SonarSource = "C:\SonarQube\sonarqube-5.1.2"
       )

       if(-not(Join-Path $SonarSource "bin\windows-x86-64\InstallNTService.bat" | Test-Path))
       {
              throw "Failed to find a sonarqube installation file"
       }

       if(( Get-Service |? {$_.Name -eq "SonarQube" }) -eq $null)
       {
              "Installing SonarQube service" | Write-Verbose
              Start-Process -FilePath (Join-Path $SonarSource "bin\windows-x86-64\InstallNTService.bat") -Wait -NoNewWindow
       }
}

#Install SonarQube Service
Install-SonarQubeService -SonarSource (Join-Path $installFolder sonarqube-5.1.2) -Verbose

Before we start the service, we need to update the log on account under which the service is running.

function Set-ServiceLogonProperties
{
       [CmdletBinding()]
       param
       (
              [Parameter(Mandatory=$false, Position=0)]
              [string] $Name = "SonarQube",

              [Parameter(Mandatory=$false, Position=1)]
              [string] $Username = "$env:USERDOMAIN\$env:USERNAME"
       )

       $credential = Get-Credential -UserName $Username -Message "Provide password"
       $password = $credential.GetNetworkCredential().Password

       $filter = 'Name=' + "'" + $Name + "'" + ''
       $service = Get-WMIObject -namespace "root\cimv2" -class Win32_Service -Filter $filter
       $service.Change($null,$null,$null,$null,$null,$null,$Username,$password)
       $service.StopService()

       while ($service.Started)
       {
              sleep 2
              $service = Get-WMIObject -namespace "root\cimv2" -class Win32_Service -Filter $filter
       }
       $service.StartService()
}
#Setup sonarqube service account credentials
Set-ServiceLogonProperties -Verbose


That's all we need. To test the installation open the url http://localhost:9000  in your browser and you should be able to see the SonarQube website up and running.

The entire source code is downloadable from GitHub from https://github.com/prajeeshprathap/Powershell-PowerPack/tree/master/SonarQube


No comments: