Initial commit version
This commit is contained in:
commit
889206ca03
440
Install-PromtailOnWindows.ps1
Normal file
440
Install-PromtailOnWindows.ps1
Normal file
@ -0,0 +1,440 @@
|
||||
#############################################################################################
|
||||
# This script downloads, if necessary, Promtail and its WinSW (Windows Service wrapper),
|
||||
# creates default configuration and creates Windows service.
|
||||
# It's a decision based script.
|
||||
#
|
||||
# ↓ ↓ ↓ ↓ HELPER FUNCTIONS ↓ ↓ ↓ ↓
|
||||
# ↓↓↓↓↓↓↓ PROCESSING CODE ↓↓↓↓↓↓↓
|
||||
#############################################################################################
|
||||
|
||||
param(
|
||||
## https://devblogs.microsoft.com/powershell/v2-custom-enums/ better, but limited to alphanumeric, so *DHCP would not work
|
||||
[Parameter(Mandatory=$true, HelpMessage="Hotel site e.g. gb-bw-peartree-manchester, bikes, gb-ihg-holidayinn-birmingham")][String]$HotelGroup,
|
||||
[Parameter(Mandatory=$true, HelpMessage="Hotel site e.g. operaapp, checkin, ")][ValidateSet('operaapp','checkin','hopapp')][String]$apptype,
|
||||
[Parameter(Mandatory=$true, HelpMessage="Have you updated the following Group Policy? Computerconfig > windows settings > security settings > advanced audit policy config > object access > double click audit removable storage.(yes/no)")][ValidateSet('yes')][String]$gpochange
|
||||
)
|
||||
|
||||
function Prompt-User {
|
||||
param(
|
||||
[string]$Prompt,
|
||||
[object]$Default
|
||||
)
|
||||
|
||||
if (-not [string]::IsNullOrEmpty($Default)) {
|
||||
if ($Default -is [bool]) {
|
||||
$Prompt += " [$(if ($Default) {'True'} else {'False'})]"
|
||||
}
|
||||
else {
|
||||
$Prompt += " [$Default]"
|
||||
}
|
||||
}
|
||||
|
||||
$input = Read-Host -Prompt $Prompt
|
||||
|
||||
if ([string]::IsNullOrEmpty($input)) {
|
||||
$input = $Default
|
||||
}
|
||||
else {
|
||||
if ($Default -is [bool]) {
|
||||
$input = [bool]::Parse($input)
|
||||
}
|
||||
elseif ($Default -is [int]) {
|
||||
$input = [int]::Parse($input)
|
||||
}
|
||||
elseif ($Default -is [string]) {
|
||||
# No conversion needed for string
|
||||
}
|
||||
else {
|
||||
throw "Unsupported default value type: $($Default.GetType().FullName)"
|
||||
}
|
||||
|
||||
if ($input.GetType() -ne $Default.GetType()) {
|
||||
throw "Entered value type doesn't match default value type"
|
||||
}
|
||||
}
|
||||
|
||||
return $input
|
||||
}
|
||||
|
||||
function Ensure-Directory {
|
||||
param(
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
if (-not [System.IO.Directory]::Exists($Path)) {
|
||||
[System.IO.Directory]::CreateDirectory($Path) | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
function Download-File {
|
||||
param (
|
||||
# Url of file to download
|
||||
[Parameter(Mandatory)]
|
||||
[string]$URL,
|
||||
|
||||
# Parameter help description
|
||||
[Parameter(Mandatory)]
|
||||
[string]$File
|
||||
)
|
||||
Begin {
|
||||
function Show-Progress {
|
||||
param (
|
||||
# Enter total value
|
||||
[Parameter(Mandatory)]
|
||||
[Single]$TotalValue,
|
||||
|
||||
# Enter current value
|
||||
[Parameter(Mandatory)]
|
||||
[Single]$CurrentValue,
|
||||
|
||||
# Enter custom progresstext
|
||||
[Parameter(Mandatory)]
|
||||
[string]$ProgressText,
|
||||
|
||||
# Enter value suffix
|
||||
[Parameter()]
|
||||
[string]$ValueSuffix,
|
||||
|
||||
# Enter bar lengh suffix
|
||||
[Parameter()]
|
||||
[int]$BarSize = 40,
|
||||
|
||||
# show complete bar
|
||||
[Parameter()]
|
||||
[switch]$Complete
|
||||
)
|
||||
|
||||
# calc %
|
||||
$percent = $CurrentValue / $TotalValue
|
||||
$percentComplete = $percent * 100
|
||||
if ($ValueSuffix) {
|
||||
$ValueSuffix = " $ValueSuffix" # add space in front
|
||||
}
|
||||
if ($psISE) {
|
||||
Write-Progress "$ProgressText $CurrentValue$ValueSuffix of $TotalValue$ValueSuffix" -id 0 -percentComplete $percentComplete
|
||||
}
|
||||
else {
|
||||
# build progressbar with string function
|
||||
$curBarSize = $BarSize * $percent
|
||||
$progbar = ""
|
||||
$progbar = $progbar.PadRight($curBarSize, [char]9608)
|
||||
$progbar = $progbar.PadRight($BarSize, [char]9617)
|
||||
|
||||
if (!$Complete.IsPresent) {
|
||||
Write-Host -NoNewLine "`r$ProgressText $progbar [ $($CurrentValue.ToString("#.###").PadLeft($TotalValue.ToString("#.###").Length))$ValueSuffix / $($TotalValue.ToString("#.###"))$ValueSuffix ] $($percentComplete.ToString("##0.00").PadLeft(6)) % complete"
|
||||
}
|
||||
else {
|
||||
Write-Host -NoNewLine "`r$ProgressText $progbar [ $($TotalValue.ToString("#.###").PadLeft($TotalValue.ToString("#.###").Length))$ValueSuffix / $($TotalValue.ToString("#.###"))$ValueSuffix ] $($percentComplete.ToString("##0.00").PadLeft(6)) % complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Process {
|
||||
try {
|
||||
$storeEAP = $ErrorActionPreference
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# invoke request
|
||||
$request = [System.Net.HttpWebRequest]::Create($URL)
|
||||
$response = $request.GetResponse()
|
||||
|
||||
if ($response.StatusCode -eq 401 -or $response.StatusCode -eq 403 -or $response.StatusCode -eq 404) {
|
||||
throw "Remote file either doesn't exist, is unauthorized, or is forbidden for '$URL'."
|
||||
}
|
||||
|
||||
if ($File -match '^\.\\') {
|
||||
$File = Join-Path (Get-Location -PSProvider "FileSystem") ($File -Split '^\.')[1]
|
||||
}
|
||||
|
||||
if ($File -and !(Split-Path $File)) {
|
||||
$File = Join-Path (Get-Location -PSProvider "FileSystem") $File
|
||||
}
|
||||
|
||||
if ($File) {
|
||||
$fileDirectory = $([System.IO.Path]::GetDirectoryName($File))
|
||||
if (!(Test-Path($fileDirectory))) {
|
||||
[System.IO.Directory]::CreateDirectory($fileDirectory) | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
[long]$fullSize = $response.ContentLength
|
||||
$fullSizeMB = $fullSize / 1024 / 1024
|
||||
|
||||
# define buffer
|
||||
[byte[]]$buffer = new-object byte[] 1048576
|
||||
[long]$total = [long]$count = 0
|
||||
|
||||
# create reader / writer
|
||||
$reader = $response.GetResponseStream()
|
||||
$writer = new-object System.IO.FileStream $File, "Create"
|
||||
|
||||
# start download
|
||||
$finalBarCount = 0 #show final bar only one time
|
||||
do {
|
||||
|
||||
$count = $reader.Read($buffer, 0, $buffer.Length)
|
||||
|
||||
$writer.Write($buffer, 0, $count)
|
||||
|
||||
$total += $count
|
||||
$totalMB = $total / 1024 / 1024
|
||||
|
||||
if ($fullSize -gt 0) {
|
||||
Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix "MB"
|
||||
}
|
||||
|
||||
if ($total -eq $fullSize -and $count -eq 0 -and $finalBarCount -eq 0) {
|
||||
Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix "MB" -Complete
|
||||
$finalBarCount++
|
||||
#Write-Host "$finalBarCount"
|
||||
}
|
||||
|
||||
} while ($count -gt 0)
|
||||
}
|
||||
|
||||
catch {
|
||||
|
||||
$ExeptionMsg = $_.Exception.Message
|
||||
Write-Host "Download breaks with error : $ExeptionMsg"
|
||||
}
|
||||
|
||||
finally {
|
||||
# cleanup
|
||||
if ($reader) { $reader.Close() }
|
||||
if ($writer) { $writer.Flush(); $writer.Close() }
|
||||
|
||||
$ErrorActionPreference = $storeEAP
|
||||
[GC]::Collect()
|
||||
|
||||
Write-Host
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function New-DefaultConfig {
|
||||
param (
|
||||
# Parameter help description
|
||||
[Parameter(Mandatory)]
|
||||
[string]$fullConfigPath,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$runPath
|
||||
)
|
||||
|
||||
Write-Output "Writing default config to $fullConfigPath"
|
||||
|
||||
$positionsFullpath = $runPath + "\positions.yaml"
|
||||
|
||||
$content = "
|
||||
# 1. Update positions.yaml path
|
||||
# 2. Update client's url - this is the url of Loki service - update or remove basic_auth
|
||||
# 3. Update what logs should be scraped
|
||||
|
||||
|
||||
server:
|
||||
http_listen_port: 9081
|
||||
grpc_listen_port: 0
|
||||
|
||||
positions:
|
||||
filename: 'C:\ProgramData\Promtail\positions.txt'
|
||||
|
||||
clients:
|
||||
- url: 'https://loki.futuresens.co.uk/loki/api/v1/push'
|
||||
|
||||
scrape_configs:
|
||||
- job_name: testapptype
|
||||
static_configs:
|
||||
- targets:
|
||||
- localhost
|
||||
labels:
|
||||
hotel: testhotel
|
||||
job: testapptype
|
||||
__path__: 'C:\Program Files\Self-Service Technology\Logs\testhotel.log'
|
||||
- job_name: sst
|
||||
static_configs:
|
||||
- targets:
|
||||
- localhost
|
||||
labels:
|
||||
hotel: testhotel
|
||||
job: sst
|
||||
__path__: 'C:\Program Files\Self-Service Technology\Logs\SST.Browser.log'
|
||||
- job_name: windows-system
|
||||
windows_events:
|
||||
eventlog_name: 'Microsoft-Windows-DriverFrameworks-UserMode/Operational'
|
||||
labels:
|
||||
logsource: windows-eventlog
|
||||
use_incoming_timestamp: true
|
||||
bookmark_path: 'C:\ProgramData\Promtail\bookmark-system.xml'
|
||||
exclude_event_data: true
|
||||
exclude_user_data: true
|
||||
locale: 1033
|
||||
"
|
||||
$content = $content.Replace('testhotel',"$HotelGroup")
|
||||
$content = $content.Replace('testapptype',"$apptype")
|
||||
Set-Content -Path $fullConfigPath -Value $content
|
||||
}
|
||||
|
||||
function New-DefaultWinSWConfig {
|
||||
param (
|
||||
# Parameter help description
|
||||
[Parameter(Mandatory)]
|
||||
[string]$fullConfigPath,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$fullPromtailBinPath,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$fullPromtailConfigPath,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$serviceName,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$serviceDisplayName
|
||||
)
|
||||
|
||||
Write-Output "Writing default WinSW config to $fullConfigPath"
|
||||
|
||||
$content = "
|
||||
<!--
|
||||
You can find more information about the configuration options here: https://github.com/kohsuke/winsw/blob/master/doc/xmlConfigFile.md
|
||||
Full example: https://github.com/kohsuke/winsw/blob/master/examples/sample-allOptions.xml
|
||||
-->
|
||||
<service>
|
||||
|
||||
<!-- ID of the service. It should be unique across the Windows system-->
|
||||
<id>$serviceName</id>
|
||||
<!-- Display name of the service -->
|
||||
<name>$serviceDisplayName</name>
|
||||
<!-- Service description -->
|
||||
<description>Starts a local Promtail service and scrapes logs according to configuration file: $fullPromtailConfigPath</description>
|
||||
|
||||
<!-- Path to the executable, which should be started -->
|
||||
<executable>""$fullPromtailBinPath""</executable>
|
||||
|
||||
<arguments>--config.file=""$fullPromtailConfigPath""</arguments>
|
||||
|
||||
</service>
|
||||
"
|
||||
|
||||
Set-Content -Path $fullConfigPath -Value $content
|
||||
}
|
||||
|
||||
|
||||
#############################################
|
||||
# ↑ ↑ ↑ ↑ HELPER FUNCTIONS ↑ ↑ ↑ ↑
|
||||
#
|
||||
#
|
||||
# ↓ ↓ ↓ ↓ PROCESSING CODE ↓ ↓ ↓ ↓
|
||||
#############################################
|
||||
|
||||
|
||||
Write-Warning -Message "This script creates a Window Service for Promtail log scraper. It is necessary to run it with Admin priviledges.
|
||||
|
||||
It can download necessary files from the Internet, but you can also put already downloaded files directly to proper directories."
|
||||
|
||||
## Below will enable event logs to allow the USB decetion logs.
|
||||
|
||||
$logDetails = Get-LogProperties 'Microsoft-Windows-DriverFrameworks-UserMode/Operational'
|
||||
$logDetails.Enabled = $True
|
||||
Set-LogProperties -LogDetails $logDetails
|
||||
Get-LogProperties 'Microsoft-Windows-DriverFrameworks-UserMode/Operational'
|
||||
|
||||
$downloadUrl = "https://github.com/grafana/loki/releases/download/v2.9.5/promtail-windows-amd64.exe.zip"
|
||||
$downloadWinSWUrl = "https://github.com/winsw/winsw/releases/download/v2.12.0/WinSW-x64.exe"
|
||||
$winSWFilename = "WinSW-x64.exe"
|
||||
$binFilename = "promtail-windows-amd64.exe"
|
||||
$configFilename = "promtail.yml"
|
||||
$winSWConfigFilename = "WinSW-x64.xml"
|
||||
|
||||
$runPath = Prompt-User -Prompt "Run directory" -Default "C:\Promtail"
|
||||
$fullBinPath = Join-Path -Path $runPath -ChildPath $binFilename
|
||||
$fullWinSWBinPath = Join-Path -Path $runPath -ChildPath $winSWFilename
|
||||
$downloadWinSWPath = $runPath
|
||||
|
||||
$shouldDownloadPromtail = Prompt-User -Prompt "Should we download Promtail?" -Default $true
|
||||
|
||||
if ($shouldDownloadPromtail) {
|
||||
$downloadUrl = Prompt-User -Prompt "Download url" -Default $downloadUrl
|
||||
$downloadPath = Prompt-User -Prompt "Download directory" -Default $runPath
|
||||
|
||||
Ensure-Directory -Path $downloadPath
|
||||
|
||||
$filename = $downloadUrl.Split("/")[-1]
|
||||
$fullPath = Join-Path -Path $downloadPath -ChildPath $filename
|
||||
|
||||
Write-Host "Downloading archive..."
|
||||
Download-File -URL $downloadUrl -File $fullPath
|
||||
|
||||
Write-Host "Expanding archive..."
|
||||
Expand-Archive -LiteralPath $fullPath -DestinationPath $runPath -Force
|
||||
}
|
||||
else {
|
||||
if (-not [System.IO.File]::Exists($fullBinPath)) {
|
||||
throw "Could not find $fullBinPath"
|
||||
}
|
||||
}
|
||||
|
||||
$shouldCreateConfig = Prompt-User -Prompt "Create default promtail.yml config?" -Default $true
|
||||
$configFullpath = Join-Path -Path $runPath -ChildPath $configFilename
|
||||
|
||||
if ($shouldCreateConfig) {
|
||||
New-DefaultConfig -fullConfigPath $configFullpath -runPath $runPath
|
||||
}
|
||||
else {
|
||||
$configFullpath = Prompt-User -Prompt "Promtail configuration file path" -Default $configFullpath
|
||||
|
||||
if (-not [System.IO.File]::Exists($configFullpath)) {
|
||||
throw "Could not find $configFullpath"
|
||||
}
|
||||
}
|
||||
|
||||
$shouldCreateService = Prompt-User -Prompt "Create Promtail Windows service?" -Default $true
|
||||
|
||||
if ($shouldCreateService) {
|
||||
|
||||
$shouldDownloadWinSWUrl = Prompt-User -Prompt "Should we download Windows Service wrapper (WinSWUrl)?" -Default $true
|
||||
|
||||
if ($shouldDownloadWinSWUrl) {
|
||||
$downloadUrl = Prompt-User -Prompt "Download url" -Default $downloadWinSWUrl
|
||||
$downloadWinSWPath = Prompt-User -Prompt "Download directory" -Default $runPath
|
||||
|
||||
Ensure-Directory -Path $downloadPath
|
||||
|
||||
$filename = $winSWFilename
|
||||
$fullWinSWBinPath = Join-Path -Path $downloadWinSWPath -ChildPath $filename
|
||||
|
||||
Write-Host "Downloading WinSW exe file..."
|
||||
Download-File -URL $downloadUrl -File $fullWinSWBinPath
|
||||
}
|
||||
else {
|
||||
if (-not [System.IO.File]::Exists($fullWinSWBinPath)) {
|
||||
throw "Could not find $fullWinSWBinPath"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$winSWconfigFullpath = Join-Path -Path $downloadWinSWPath -ChildPath $winSWConfigFilename
|
||||
$shouldCreateWinSWConfig = Prompt-User -Prompt "Create WinSW config as $winSWconfigFullpath ?" -Default $true
|
||||
|
||||
if ($shouldCreateWinSWConfig) {
|
||||
$serviceName = Prompt-User -Prompt "Service name" -Default "Promtail"
|
||||
$serviceDisplayName = Prompt-User -Prompt "Service name" -Default "Promtail Logs scraper"
|
||||
|
||||
New-DefaultWinSWConfig -fullConfigPath $winSWconfigFullpath -fullPromtailBinPath $fullBinPath -fullPromtailConfigPath $configFullpath -serviceName $serviceName -serviceDisplayName $serviceDisplayName
|
||||
}
|
||||
else {
|
||||
if (-not [System.IO.File]::Exists($winSWconfigFullpath)) {
|
||||
throw "Could not find $winSWconfigFullpath"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Installing Promtail Windows Service"
|
||||
|
||||
Start-Process -FilePath $fullWinSWBinPath -ArgumentList @("install") -NoNewWindow
|
||||
|
||||
Write-Host "Starting the Service"
|
||||
|
||||
start-sleep -Seconds 5
|
||||
|
||||
Start-Service Promtail
|
||||
|
||||
Set-ExecutionPolicy Restricted -Force
|
||||
|
||||
Write-Host "Reverting execution policy"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user