Skip to content
This repository has been archived by the owner on Feb 19, 2019. It is now read-only.

(GH-489) Install-ChocolateyService feature #506

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
476c823
Work on #489. Install-ChocolateyService created. Entry function added…
030 Jul 4, 2014
61581b1
Work on #489. Creating Pester test for Install-ChocolateyService
030 Jul 4, 2014
e6e507d
Work on #489. Creating Pester test for Install-ChocolateyService
030 Jul 4, 2014
0a73276
Work on #489. Created tests to validate all input parameters
030 Jul 5, 2014
100209e
Work on #489. Multiple functions created
030 Jul 5, 2014
51906e2
(GH-489) Multiple functions created
030 Jul 5, 2014
0b99c70
(GH-489) Port changed from required to optional
030 Jul 5, 2014
3df0334
(GH-489) Functions inside function issue solved
030 Jul 6, 2014
f5d1e88
(GH-489) Details about how to install services removed
030 Jul 6, 2014
2f24256
(GH-489) Created tests
030 Jul 6, 2014
6c93cac
(GH-489) Moved Install-ChocolateyService parameter to the end of file…
030 Jul 6, 2014
e8a7bb5
(GH-489) Function created to test whether service exists
030 Jul 6, 2014
8a5cccb
(GH-489) Function created to test whether status is running or stopped
030 Jul 6, 2014
f5a2873
(GH-489) ServiceExistence and Status functions moved from functions t…
030 Jul 6, 2014
0685746
(GH-489) Service create to delete services
030 Jul 6, 2014
26011d9
(GH-489) Get-ServiceExistence, Service-Status and Delete-Service func…
030 Jul 6, 2014
1658dd5
(GH-489) Function created to test Install-ChocolateyService if valid …
030 Jul 6, 2014
fb2236f
(GH-489) For loop created to start service 12 times with an interval …
030 Jul 6, 2014
ee0bfa7
(GH-489) Test created to test validity of installCommand and serviceS…
030 Jul 6, 2014
6a603b7
(GH-489) Delete-Service changed to Remove-Service as Delete was not a…
030 Jul 8, 2014
06a4985
(GH-489) Incorrect Debug-information fixed
030 Jul 8, 2014
992daad
(GH-506) Documentation added
030 Jul 8, 2014
715aec8
(GH-506) Remove-Service changed to Uninstall-ChocolateyService.
030 Jul 8, 2014
85ee219
(GH-489) Some real live examples added to demonstrate how to install …
030 Jul 14, 2014
ecb79fa
(GH-489) test if port is available then it should indicate that it is…
Aug 23, 2014
0fc9405
(GH-489) removed unnecessary test as only throwing an exception is su…
Aug 23, 2014
2dbf542
(GH-489) only throw error if port is passed and if this is in LISTENI…
Aug 23, 2014
b91a554
(GH-489) removed available port variable from test as this is not use…
030 Aug 23, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/helpers/chocolateyInstaller.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@ Export-ModuleMember -Function `
Update-SessionEnvironment,`
Get-EnvironmentVariableNames,`
Get-EnvironmentVariable,`
Set-EnvironmentVariable
Set-EnvironmentVariable,`
Install-ChocolateyService,`
Get-ServiceExistence,`
Get-ServiceStatus,`
Uninstall-ChocolateyService,`
Remove-ChocolateyDirectory
6 changes: 6 additions & 0 deletions src/helpers/functions/Get-ServiceExistence.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function Get-ServiceExistence {
param(
[string] $serviceName = ''
)
Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"
}
7 changes: 7 additions & 0 deletions src/helpers/functions/Get-ServiceStatus.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function Get-ServiceStatus {
param(
[string] $serviceName = ''
)
$serviceStatus = Get-Service -Name $serviceName
$serviceStatus.Status
}
102 changes: 102 additions & 0 deletions src/helpers/functions/Install-ChocolateyService.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
function Install-ChocolateyService {
<#
.SYNOPSIS
Installs a service

.DESCRIPTION
This will install a service

.PARAMETER PackageName
The name of the package for whom the service will be installed.

.PARAMETER ServiceName
The name of service which will be used to install and start the service.

.PARAMETER CreateServiceCommand
The command which installs the service.

.PARAMETER AvailablePort (OPTIONAL)
The port which needs to be available in order to start the service.

.EXAMPLE
Install-ChocolateyService 'PACKAGE_NAME' 'SERVICE_NAME' 'INSTALL_COMMAND' 'PORT'
Install-ChocolateyService "dcm4chee" "DCM4CHEE" "nssm install DCM4CHEE `"java`" -jar `"%DCM4CHEE_HOME%/bin/run.jar"`" "8090"
Install-ChocolateyService "postgresqlzip" "PostgreSQL" "pg_ctl register -N `"PostgreSQL`" -U `"LocalSystem`" -w" "5432"
Install-ChocolateyService "apacheds" "ApacheDS" "nssm install ApacheDS `"java`" -jar `"%APACHEDS_HOME%/lib/apacheds-service-${version}.jar`" `"%APACHEDS_HOME%/instances/default`"" "10389"
Install-ChocolateyService "test" "test" "nssm install test `"$testDirectory\testService.bat`""

.OUTPUTS
None

.NOTES
This helper reduces the number of lines one would have to write to install a service to 1 line.
This method has error handling built into it.

.LINK
Uninstall-ChocolateyService
Get-ServiceExistence
#>
param(
[string] $packageName,
[string] $serviceName,
[string] $createServiceCommand,
[int] $availablePort
)
Write-Debug "Running 'Install-ChocolateyService' for $packageName with serviceName:`'$serviceName`', createServiceCommand: `'$createServiceCommand`', availablePort: `'$availablePort`' ";

if(!$packageName) {
Write-ChocolateyFailure "Install-ChocolateyService" "Missing PackageName input parameter."
return
}

if(!$serviceName) {
Write-ChocolateyFailure "Install-ChocolateyService" "Missing ServiceName input parameter."
return
}

if(!$createServiceCommand) {
Write-ChocolateyFailure "Install-ChocolateyService" "Missing CreateServiceCommand input parameter."
return
}

$listeningStatePort = Get-NetTCPConnection -State Listen | Where-Object {$_.LocalAddress -eq "0.0.0.0" -and $_.LocalPort -eq "$availablePort"}

try {
Uninstall-ChocolateyService -serviceName "$serviceName"

try {
Write-Host "$packageName service will be installed"
Write-Host $createServiceCommand
iex $createServiceCommand
} catch {
Write-ChocolateyFailure "Install-ChocolateyService" "The createServiceCommand is incorrect: '$_'."
return
}

if($availablePort -and $listeningStatePort) {
Write-ChocolateyFailure "Install-ChocolateyService" "$availablePort is in LISTENING state and not available."
return
}

if (Get-ServiceExistence -serviceName "$serviceName") {
Write-Host "$packageName service will be started"

for ($i=0;$i -lt 12; $i++) {
$serviceStatus = Get-Service -Name $serviceName

start-service $serviceName

if ($serviceStatus.Status -eq "running") {
Write-Host "$packageName service has been started"
return
}
Start-Sleep -s 5
}
} else {
Write-ChocolateyFailure "Install-ChocolateyService" "service $serviceName does not exist."
return
}
} catch {
Write-ChocolateyFailure "Install-ChocolateyService" "There were errors attempting to create the $packageName service. The error message was '$_'."
}
}
10 changes: 10 additions & 0 deletions src/helpers/functions/Remove-ChocolateyDirectory.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function Remove-ChocolateyDirectory {
param(
[string] $directory
)
Write-Host "Directory `"$directory`" will be removed"

if (Test-Path $directory) {
Remove-Item -Recurse -Force $directory
}
}
11 changes: 11 additions & 0 deletions src/helpers/functions/Uninstall-ChocolateyService.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function Uninstall-ChocolateyService {
param(
[string] $serviceName = ''
)
if (Get-ServiceExistence -serviceName "$serviceName") {
Write-Host "$serviceName service already exists and will be removed"
stop-service $serviceName
$service = Get-ServiceExistence -serviceName "$serviceName"
$service.delete()
}
}
106 changes: 106 additions & 0 deletions tests/unit/Install-ChocolateyService.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
$here = Split-Path -Parent $MyInvocation.MyCommand.Definition
$common = Join-Path (Split-Path -Parent $here) '_Common.ps1'
$base = Split-Path -parent (Split-Path -Parent $here)
$baseFunctions = "$base\src\helpers\functions"
. $common
. "$baseFunctions\Install-ChocolateyService.ps1"
. "$baseFunctions\Get-ServiceExistence.ps1"
. "$baseFunctions\Get-ServiceStatus.ps1"
. "$base\tests\unit\Install-ChocolateyServiceCorrectParameters.Tests.ps1"

$unavailablePort = "135"
$correctServiceName = "installServiceTest"
$unavailableServiceName = "unavailableServiceName"
$testDirectory = "C:\installChocolateyServiceTest"

Describe "Install-ChocolateyService" {
Context "When provided parameters are correct the service should be created and started" {
Install-ChocolateyServiceCorrectParameters.Tests -testDirectory "$testDirectory"

It "service creation should succeed" {
Get-ServiceExistence -serviceName "$correctServiceName" | should Be $true
}

It "service start should succeed" {
Get-ServiceStatus -serviceName "$correctServiceName" -eq "running" | should Be $true
}
}

Context "When provided parameters are correct and service exist it should be removed, subsequently created and started" {
Install-ChocolateyServiceCorrectParameters.Tests -testDirectory "$testDirectory"

It "service creation should succeed after deletion of previous service" {
Get-ServiceExistence -serviceName "$correctServiceName" | should Be $true
}

It "service start should succeed after deletion of previous service" {
Get-ServiceStatus -serviceName "$correctServiceName" -eq "running" | should Be $true
}
}

Context "When availablePort parameter is passed to this function and it is in LISTENING state and NOT available" {
Mock Write-ChocolateyFailure

Install-ChocolateyServiceCorrectParameters.Tests -testDirectory "$testDirectory" -availablePort "$unavailablePort"

It "should return an error" {
Assert-MockCalled Write-ChocolateyFailure -parameterFilter { $failureMessage -eq "$unavailablePort is in LISTENING state and not available."
Write-Host $failureMessage
}
}
}

Context "When no packageName parameter is passed to this function" {
Mock Write-ChocolateyFailure

Install-ChocolateyService -serviceName "$unavailableServiceName" -createServiceCommand "$unavailableServiceName"

It "should return an error" {
Assert-MockCalled Write-ChocolateyFailure -parameterFilter { $failureMessage -eq "Missing PackageName input parameter." }
}
}

Context "When no serviceName parameter is passed to this function" {
Mock Write-ChocolateyFailure

Install-ChocolateyService -packageName "$unavailableServiceName" -createServiceCommand "$unavailableServiceName"

It "should return an error" {
Assert-MockCalled Write-ChocolateyFailure -parameterFilter { $failureMessage -eq "Missing ServiceName input parameter." }
}
}

Context "When no createServiceCommand parameter is passed to this function" {
Mock Write-ChocolateyFailure

Install-ChocolateyService -packageName "$unavailableServiceName" -serviceName "$unavailableServiceName"

It "should return an error" {
Assert-MockCalled Write-ChocolateyFailure -parameterFilter { $failureMessage -eq "Missing CreateServiceCommand input parameter." }
}
}

Context "When service does not exist" {
Mock Write-ChocolateyFailure

Install-ChocolateyServiceCorrectParameters.Tests -testDirectory "$testDirectory" -serviceName "$unavailableServiceName"

It "should return an error" {
Assert-MockCalled Write-ChocolateyFailure -parameterFilter { $failureMessage -eq "service unavailableServiceName does not exist." }
}
}

Context "When createServiceCommand is incorrect" {
Mock Write-ChocolateyFailure

Install-ChocolateyServiceCorrectParameters.Tests -testDirectory "$testDirectory" -createServiceCommand "$unavailableServiceName"

It "should return an error" {
Assert-MockCalled Write-ChocolateyFailure -parameterFilter { $failureMessage -eq "The createServiceCommand is incorrect: 'The term 'unavailableServiceName' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.'." }
}
}

Uninstall-ChocolateyService -serviceName "$serviceName"

Remove-ChocolateyDirectory "$testDirectory"
}
21 changes: 21 additions & 0 deletions tests/unit/Install-ChocolateyServiceCorrectParameters.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function Install-ChocolateyServiceCorrectParameters.Tests {
param(
[string] $testDirectory,
[string] $serviceName = "installServiceTest",
[string] $createServiceCommand = "nssm install installServiceTest",
[int] $availablePort
)
$testServiceBatPath = "$testDirectory\testService.bat"
$testDirectoryExist = Test-Path $testDirectory
$createServiceCommandComplete = "$createServiceCommand `"$testServiceBatPath`""

`cinst NSSM`

if (!$testDirectoryExist) {
Write-Host "$testDirectory directory does not exist and will be created"
New-Item -ItemType Directory -Path $testDirectory
Set-Content -Value "ping localhost" -Path $testServiceBatPath
}

Install-ChocolateyService -packageName "$serviceName" -serviceName "$serviceName" -createServiceCommand "$createServiceCommandComplete" -availablePort "$availablePort"
}