Hubot.psm1
# TO DO # - Make class for calling NPM Install # - Make class for getting service state # - Make it retur HubotInstall object and HubotInstallService object # - Fix Script Analyiser Warnings # Defines the values for the resource's Ensure property. enum Ensure { # The resource must be absent. Absent # The resource must be present. Present } class HubotHelpers { [string] RefreshPathVariable () { $updatedPath = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") return $updatedPath } [bool] CheckPathExists ([string]$Path) { if (Test-Path -Path $Path) { Write-Verbose "Directory $($Path) exists." return $true } else { Write-Verbose "Directory $($Path) exists." return $false } } } [DscResource()] class HubotInstall { # A DSC resource must define at least one key property. [DscProperty(Key)] [string]$BotPath [DscProperty(Mandatory)] [Ensure]$Ensure # Sets the desired state of the resource. [void] Set() { $env:Path = [HubotHelpers]::new().RefreshPathVariable() $nodeModulesPath = Join-Path -Path $this.BotPath -ChildPath 'node_modules' if (!(Test-Path -Path $this.BotPath)) { throw "The path $($this.BotPath) must exist and contain a Hubot installation in it. You can clone one from here: https://github.com/MattHodge/HubotWindows" } if ($this.Ensure -eq [Ensure]::Present) { $npmCmd = 'install' } else { $npmCmd = 'uninstall' } Write-Verbose -Message "$($npmCmd)ing CoffeeScript at $($this.BotPath)" Start-Process -FilePath npm -ArgumentList "$($npmCmd) coffee-script" -Wait -NoNewWindow -WorkingDirectory $this.BotPath Write-Verbose "$($npmCmd)ing all required npm modules" Start-Process -FilePath npm -ArgumentList "$($npmCmd)" -Wait -NoNewWindow -WorkingDirectory $this.BotPath if ($this.Ensure -eq [Ensure]::Absent) { Remove-Item -Path $nodeModulesPath -Force } } # Tests if the resource is in the desired state. [bool] Test() { $nodeModulesPath = Join-Path -Path $this.BotPath -ChildPath 'node_modules' # present case if ($this.Ensure -eq [Ensure]::Present) { return [HubotHelpers]::new().CheckPathExists($nodeModulesPath) } # absent case else { return (![HubotHelpers]::new().CheckPathExists($nodeModulesPath)) } } # Gets the resource's current state. [HubotInstall] Get() { return @{ BotConfigPath = $this.BotPath Ensure = $this.Ensure } } } [DscResource()] class HubotInstallService { # Path where the Hubot is located [DscProperty(Key)] [string]$BotPath # Name for the Hubot service [DscProperty(Mandatory)] [string]$ServiceName # Credential to run the service under [DscProperty()] [PSCredential]$Credential # Bot adapter for Hubot to be used. Used as a paramater to start the server (-a $botadapter) [DscProperty(Mandatory)] [string]$BotAdapter [DscProperty(Mandatory)] [Ensure]$Ensure [void] Set() { if (Get-Command -CommandType Application -Name nssm -ErrorAction SilentlyContinue) { $nssmPath = (Get-Command -CommandType Application -Name nssm).Source } else { throw "nssm.exe cannot be found. Cannot continue. Have you run the HubotInstall resource?" } $env:Path = [HubotHelpers]::new().RefreshPathVariable() if ($this.Ensure -eq [Ensure]::Present) { if (Get-Service -Name $this.ServiceName -ErrorAction SilentlyContinue) { Write-Verbose "Removing old service" Stop-Service -Name $this.ServiceName -Force Start-Process -FilePath $nssmPath -ArgumentList "remove $($this.ServiceName) confirm" -Wait -NoNewWindow } $botLogPath = Join-Path -Path $this.BotPath -ChildPath 'Logs' Write-Verbose "Creating bot logging path at $($botLogPath)" New-Item -Path $botLogPath -Force -ItemType Directory Write-Verbose "Installing Bot Service $($this.ServiceName)" Start-Process -FilePath $nssmPath -ArgumentList "install $($this.ServiceName) node" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) AppDirectory $($this.BotPath)" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) AppParameters "".\node_modules\coffee-script\bin\coffee .\node_modules\hubot\bin\hubot -a $($this.BotAdapter)""" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) AppStdout ""$($botLogPath)\$($this.ServiceName)_log.txt""" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) AppStderr ""$($botLogPath)\$($this.ServiceName)_error.txt""" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) AppRotateFiles 1" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) AppRotateOnline 1" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) AppRotateSeconds 86400" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) Description Hubot Service" -Wait -NoNewWindow Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) Start SERVICE_AUTO_START" -Wait -NoNewWindow # if a credetial is passed with no password assume LocalSystem if ([string]::IsNullOrEmpty($this.Credential.UserName)) { Write-Verbose "No credential passed, using LocalSystem." Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) ObjectName LocalSystem" -Wait -NoNewWindow } # if a credential is passed with a password else { Write-Verbose "Credential passed, using username $($this.Credential.UserName)." Start-Process -FilePath $nssmPath -ArgumentList "set $($this.ServiceName) ObjectName .\$($this.Credential.UserName) $($this.Credential.GetNetworkCredential().Password)" -Wait -NoNewWindow } Start-Service -Name $this.ServiceName } else { Write-Verbose "Removing Bot Service $($this.ServiceName)" Stop-Service -Name $this.ServiceName -Force -ErrorAction SilentlyContinue Start-Process -FilePath $nssmPath -ArgumentList "remove $($this.ServiceName) confirm" -Wait -NoNewWindow } } # Tests if the resource is in the desired state. [bool] Test() { # present case if ($this.Ensure -eq [Ensure]::Present) { # array to store stat $states = @() if (Get-Service -Name $this.ServiceName -ErrorAction SilentlyContinue) { $states += $true if ((Get-Service -Name $this.ServiceName).Status -eq 'Running') { $states += $true } else { $states += $false } } else { $states += $false } if ($states -notcontains $false) { return $true } else { return $false } } # absent case else { if (Get-Service -Name $this.ServiceName -ErrorAction SilentlyContinue) { return $false } else { return $true } } } # Gets the resource's current state. [HubotInstallService] Get() { return @{ BotPath = $this.BotPath ServiceName = $this.ServiceName BotAdapter = $this.BotAdapter Ensure = $this.Ensure } } } |