Skip to content

Commit 8782a3b

Browse files
authored
Merge pull request #2045 from twangboy/update_bootstrap
Make universal repo url
2 parents b2545a2 + e6e5cd6 commit 8782a3b

File tree

1 file changed

+147
-109
lines changed

1 file changed

+147
-109
lines changed

bootstrap-salt.ps1

Lines changed: 147 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
[CmdletBinding()]
4949
param(
5050
[Parameter(Mandatory=$false, ValueFromPipeline=$True)]
51-
[ValidatePattern('^(\d{4}(\.\d{1,2}){0,2}(\-\d{1})?)|(latest)$', Options=1)]
5251
[Alias("v")]
5352
# The version of the Salt minion to install. Default is "latest" which will
5453
# install the latest version of Salt minion available. Doesn't support
@@ -153,34 +152,116 @@ function Get-MajorVersion {
153152
return ( $Version -split "\." )[0]
154153
}
155154

156-
function Convert-PSObjectToHashtable {
157-
param (
158-
[Parameter(ValueFromPipeline)]
159-
$InputObject
160-
)
161-
if ($null -eq $InputObject) { return $null }
162-
163-
$is_enum = $InputObject -is [System.Collections.IEnumerable]
164-
$not_string = $InputObject -isnot [string]
165-
if ($is_enum -and $not_string) {
166-
$collection = @(
167-
foreach ($object in $InputObject) {
168-
Convert-PSObjectToHashtable $object
169-
}
170-
)
155+
function Get-AvailableVersions {
156+
# Get available versions from a remote location specified in the Source
157+
# Parameter
158+
Write-Verbose "Getting version information from the repo"
159+
Write-Verbose "base_url: $base_url"
160+
161+
$available_versions = [System.Collections.ArrayList]@()
162+
163+
if ( $base_url.StartsWith("http") -or $base_url.StartsWith("ftp") ) {
164+
# We're dealing with HTTP, HTTPS, or FTP
165+
$response = Invoke-WebRequest "$base_url" -UseBasicParsing
166+
try {
167+
$response = Invoke-WebRequest "$base_url" -UseBasicParsing
168+
} catch {
169+
Write-Host "Failed to get version information" -ForegroundColor Red
170+
exit 1
171+
}
171172

172-
Write-Host -NoEnumerate $collection
173-
} elseif ($InputObject -is [PSObject]) {
174-
$hash = @{}
173+
if ( $response.StatusCode -ne 200 ) {
174+
Write-Host "There was an error getting version information" -ForegroundColor Red
175+
Write-Host "Error: $($response.StatusCode)" -ForegroundColor red
176+
exit 1
177+
}
175178

176-
foreach ($property in $InputObject.PSObject.Properties) {
177-
$hash[$property.Name] = Convert-PSObjectToHashtable $property.Value
179+
$response.links | ForEach-Object {
180+
if ( $_.href.Length -gt 8) {
181+
Write-Host "The content at this location is unexpected" -ForegroundColor Red
182+
Write-Host "Should be a list of directories where the name is a version of Salt" -ForegroundColor Red
183+
exit 1
184+
}
178185
}
179186

180-
$hash
187+
# Getting available versions from response
188+
Write-Verbose "Getting available versions from response"
189+
$filtered = $response.Links | Where-Object -Property href -NE "../"
190+
$filtered | Select-Object -Property href | ForEach-Object {
191+
$available_versions.Add($_.href.Trim("/")) | Out-Null
192+
}
193+
} elseif ( $base_url.StartsWith("\\") -or $base_url -match "^[A-Za-z]:\\" ) {
194+
# We're dealing with a local directory or SMB source
195+
Get-ChildItem -Path $base_url -Directory | ForEach-Object {
196+
$available_versions.Add($_.Name) | Out-Null
197+
}
181198
} else {
182-
$InputObject
199+
Write-Host "Unknown Source Type" -ForegroundColor Red
200+
Write-Host "Must be one of HTTP, HTTPS, FTP, SMB Share, Local Directory" -ForegroundColor Red
201+
exit 1
202+
}
203+
204+
Write-Verbose "Available versions:"
205+
$available_versions | ForEach-Object {
206+
Write-Verbose "- $_"
207+
}
208+
209+
# Get the latest version, should be the last in the list
210+
Write-Verbose "Getting latest available version"
211+
$latest = $available_versions | Select-Object -Last 1
212+
Write-Verbose "Latest available version: $latest"
213+
214+
# Create a versions table
215+
# This will have the latest version available, the latest version available
216+
# for each major version, and every version available. This makes the
217+
# version lookup logic easier. The contents of the versions table can be
218+
# found by running -Verbose
219+
Write-Verbose "Populating the versions table"
220+
$versions_table = [ordered]@{"latest"=$latest}
221+
$available_versions | ForEach-Object {
222+
$versions_table[$(Get-MajorVersion $_)] = $_
223+
$versions_table[$_.ToLower()] = $_.ToLower()
224+
}
225+
226+
Write-Verbose "Versions Table:"
227+
$versions_table | Sort-Object Name | Out-String | ForEach-Object {
228+
Write-Verbose "$_"
229+
}
230+
231+
return $versions_table
232+
}
233+
234+
function Get-HashFromArtifactory {
235+
# This function uses the artifactory API to get the SHA265 Hash for the file
236+
# If Source is NOT artifactory, the sha will not be checked
237+
[CmdletBinding()]
238+
param(
239+
[Parameter(Mandatory=$true)]
240+
[String] $SaltVersion,
241+
242+
[Parameter(Mandatory=$true)]
243+
[String] $SaltFileName
244+
)
245+
if ( $api_url ) {
246+
$full_url = "$api_url/$SaltVersion/$SaltFileName"
247+
Write-Verbose "Querying Artifactory API for hash:"
248+
Write-Verbose $full_url
249+
try {
250+
$response = Invoke-RestMethod $full_url -UseBasicParsing
251+
return $response.checksums.sha256
252+
} catch {
253+
Write-Verbose "Artifactory API Not available or file not"
254+
Write-Verbose "available at specified location"
255+
Write-Verbose "Hash will not be checked"
256+
return ""
257+
}
258+
Write-Verbose "No hash found for this file: $SaltFileName"
259+
Write-Verbose "Hash will not be checked"
260+
return ""
183261
}
262+
Write-Verbose "No artifactory API defined"
263+
Write-Verbose "Hash will not be checked"
264+
return ""
184265
}
185266

186267
function Get-FileHash {
@@ -313,10 +394,8 @@ if ($majorVersion -lt "3006") {
313394
#===============================================================================
314395
$ConfDir = "$RootDir\conf"
315396
$PkiDir = "$ConfDir\pki\minion"
316-
$RootDir = "$env:ProgramData\Salt Project\Salt"
317-
$DfltUrl = "https://packages.broadcom.com/artifactory/saltproject-generic/windows/"
318-
$ApiUrl = "https://packages.broadcom.com/artifactory/api/storage/saltproject-generic/windows"
319397

398+
$RootDir = "$env:ProgramData\Salt Project\Salt"
320399
# Check for existing installation where RootDir is stored in the registry
321400
$SaltRegKey = "HKLM:\SOFTWARE\Salt Project\Salt"
322401
if (Test-Path -Path $SaltRegKey) {
@@ -325,6 +404,18 @@ if (Test-Path -Path $SaltRegKey) {
325404
}
326405
}
327406

407+
# Get repo and api URLs. An artifactory URL will have "artifactory" in it
408+
$domain, $target = $RepoUrl -split "/artifactory/"
409+
if ( $target ) {
410+
# Create $base_url and $api_url
411+
$base_url = "$domain/artifactory/$target"
412+
$api_url = "$domain/artifactory/api/storage/$target"
413+
} else {
414+
# This is a non-artifactory url, there is no api
415+
$base_url = $domain
416+
$api_url = ""
417+
}
418+
328419
#===============================================================================
329420
# Verify Parameters
330421
#===============================================================================
@@ -335,8 +426,8 @@ Write-Verbose "version: $Version"
335426
Write-Verbose "runservice: $RunService"
336427
Write-Verbose "master: $Master"
337428
Write-Verbose "minion: $Minion"
338-
Write-Verbose "repourl: $RepoUrl"
339-
Write-Verbose "apiurl: $ApiUrl"
429+
Write-Verbose "repourl: $base_url"
430+
Write-Verbose "apiurl: $api_url"
340431
Write-Verbose "ConfDir: $ConfDir"
341432
Write-Verbose "RootDir: $RootDir"
342433

@@ -393,98 +484,42 @@ if ( $ConfigureOnly ) {
393484
#===============================================================================
394485
# Detect architecture
395486
#===============================================================================
396-
if ([IntPtr]::Size -eq 4) {
397-
$arch = "x86"
398-
} else {
399-
$arch = "AMD64"
400-
}
487+
if ([IntPtr]::Size -eq 4) { $arch = "x86" } else { $arch = "AMD64" }
401488

402489
#===============================================================================
403490
# Getting version information from the repo
404491
#===============================================================================
405-
if ( $RepoUrl -eq $DfltUrl ) {
406-
Write-Verbose "Getting version information from Artifactory"
407-
$response = Invoke-WebRequest $ApiUrl -UseBasicParsing
408-
# Convert the output to a powershell object
409-
$psobj = $response.ToString() | ConvertFrom-Json
410-
411-
# Filter the object for folders
412-
$filtered = $psobj.children | Where-Object -Property folder -EQ $true
413-
414-
# Get each uri and add it to the list of versions
415-
$available_versions = [System.Collections.ArrayList]@()
416-
$filtered | Select-Object -Property uri | ForEach-Object {
417-
$available_versions.Add($_.uri.Trim("/")) | Out-Null
418-
}
492+
$versions = Get-AvailableVersions
419493

420-
# Create a versions table, similar to repo.json
421-
# This will have the latest version available, the latest version available for
422-
# each major version, and every version available. This makes the version
423-
# lookup logic easier. You can view the contents of the versions table by
424-
# passing the -Verbose command
425-
$latest = $available_versions | Select-Object -Last 1
426-
$versions_table = [ordered]@{"latest"=$latest}
427-
428-
$available_versions | ForEach-Object {
429-
$versions_table[$(Get-MajorVersion $_)] = $_
430-
$versions_table[$_.ToLower()] = $_.ToLower()
431-
}
432-
433-
Write-Verbose "Available versions:"
434-
$available_versions | ForEach-Object {
435-
Write-Verbose "- $_"
436-
}
437-
Write-Verbose "Versions Table:"
438-
$versions_table | Sort-Object Name | Out-String | Write-Verbose
439-
440-
#===============================================================================
441-
# Validate passed version
442-
#===============================================================================
443-
if ( $versions_table.Contains($Version.ToLower()) ) {
444-
$Version = $versions_table[$Version.ToLower()]
445-
} else {
446-
Write-Host "Version $Version is not available" -ForegroundColor Red
447-
Write-Host "Available versions are:" -ForegroundColor Yellow
448-
$available_versions | ForEach-Object { Write-Host "- $_" -ForegroundColor Yellow }
449-
exit 1
450-
}
451-
452-
#===============================================================================
453-
# Get file url and sha256
454-
#===============================================================================
455-
$saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe"
456-
$response = Invoke-WebRequest "$ApiUrl/$Version/$saltFileName" -UseBasicParsing
457-
$psobj = $response.ToString() | ConvertFrom-Json
458-
$saltFileUrl = $psobj.downloadUri
459-
$saltSha256 = $psobj.checksums.sha256
460-
461-
if ( $saltFileName -and $saltVersion -and $saltSha256) {
462-
Write-Verbose "Found Name, Version, and Sha"
463-
} else {
464-
# We will guess the name of the installer
465-
Write-Verbose "Failed to get Name, Version, and Sha from Artifactory API"
466-
Write-Verbose "We'll try to find the file in standard paths"
467-
$saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe"
468-
$saltVersion = $Version
469-
}
494+
#===============================================================================
495+
# Validate passed version
496+
#===============================================================================
497+
Write-Verbose "Looking up version: $Version"
498+
if ( $versions.Contains($Version.ToLower()) ) {
499+
$Version = $versions[$Version.ToLower()]
500+
Write-Verbose "Found version: $Version"
470501
} else {
471-
# If we're using a custom RepoUrl, we're going to assum that the binary is
472-
# in the reoot of the RepoUrl/Version. We will not check the sha on custom
473-
# repos
474-
$saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe"
475-
$saltFileUrl = "$RepoUrl/$Version/$saltFileName"
476-
$saltVersion = $Version
477-
$saltSha256 = ""
502+
Write-Host "Version $Version is not available" -ForegroundColor Red
503+
Write-Host "Available versions are:" -ForegroundColor Yellow
504+
$versions
505+
exit 1
478506
}
479507

508+
#===============================================================================
509+
# Get file url and sha256
510+
#===============================================================================
511+
$saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe"
512+
$saltFileUrl = "$base_url/$Version/$saltFileName"
513+
$saltSha256 = Get-HashFromArtifactory -SaltVersion $Version -SaltFileName $saltFileName
514+
480515
#===============================================================================
481516
# Download minion setup file
482517
#===============================================================================
483518
Write-Host "===============================================================================" -ForegroundColor Yellow
484519
Write-Host " Bootstrapping Salt Minion" -ForegroundColor Green
485520
Write-Host " - version: $Version"
486521
Write-Host " - file name: $saltFileName"
487-
Write-Host " - file url: $saltFileUrl"
522+
Write-Host " - file url : $saltFileUrl"
488523
Write-Host " - file hash: $saltSha256"
489524
Write-Host " - master: $Master"
490525
Write-Host " - minion id: $Minion"
@@ -498,16 +533,19 @@ Write-Verbose ""
498533
Write-Verbose "Salt File URL: $saltFileUrl"
499534
Write-Verbose "Local File: $localFile"
500535

501-
if ( Test-Path -Path $localFile ) {Remove-Item -Path $localFile -Force}
502-
Invoke-WebRequest -Uri $saltFileUrl -OutFile $localFile
536+
# Remove existing local file
537+
if ( Test-Path -Path $localFile ) { Remove-Item -Path $localFile -Force }
503538

539+
# Download the file
540+
Invoke-WebRequest -Uri $saltFileUrl -OutFile $localFile
504541
if ( Test-Path -Path $localFile ) {
505542
Write-Host "Success" -ForegroundColor Green
506543
} else {
507544
Write-Host "Failed" -ForegroundColor Red
508545
exit 1
509546
}
510547

548+
# Compare the hash if there is a hash to compare
511549
if ( $saltSha256 ) {
512550
$localSha256 = (Get-FileHash -Path $localFile -Algorithm SHA256).Hash
513551
Write-Host "Comparing Hash: " -NoNewline
@@ -546,13 +584,13 @@ $process = Start-Process $localFile `
546584
-NoNewWindow -PassThru
547585

548586
# Sometimes the installer hangs... we'll wait 5 minutes and then kill it
549-
Write-Verbose ""
550587
Write-Verbose "Waiting for installer to finish"
551588
$process | Wait-Process -Timeout 300 -ErrorAction SilentlyContinue
552589
$process.Refresh()
553590

554591
if ( !$process.HasExited ) {
555-
Write-Host "Installer Timeout" -ForegroundColor Yellow
592+
Write-Verbose "Installer Timeout"
593+
Write-Host ""
556594
Write-Host "Killing hung installer: " -NoNewline
557595
$process | Stop-Process
558596
$process.Refresh()

0 commit comments

Comments
 (0)