From 62c5f08f6b4b2ebd612bfc9c253c7ebd5f9e6377 Mon Sep 17 00:00:00 2001 From: James Ruskin Date: Tue, 20 Aug 2024 14:34:41 +0100 Subject: [PATCH] (nexus-repository-migrator) Extracts nexus-repository Migration Logic It was raised that we should have a separate package for the Nexus Repository Migrator logic. This commit removes that code from the Nexus Repository package, and adds it to a separate package that can be installed. --- .../nexus-repository-migrator.nuspec | 78 ++++++++++ .../tools/ConvertFrom-NexusOrientDb.ps1 | 128 +++++++++++++++ .../tools/Repair-Nexus371FailedUpgrade.ps1 | 91 +++++++++++ .../tools/chocolateyInstall.ps1 | 23 +++ .../tools/chocolateyUninstall.ps1 | 4 + .../nexus-repository-migrator/update.ps1 | 39 +++++ .../tools/chocolateyinstall.ps1 | 59 +------ automatic/nexus-repository/tools/helpers.ps1 | 147 +++++++++++++++--- 8 files changed, 494 insertions(+), 75 deletions(-) create mode 100644 automatic/nexus-repository-migrator/nexus-repository-migrator.nuspec create mode 100644 automatic/nexus-repository-migrator/tools/ConvertFrom-NexusOrientDb.ps1 create mode 100644 automatic/nexus-repository-migrator/tools/Repair-Nexus371FailedUpgrade.ps1 create mode 100644 automatic/nexus-repository-migrator/tools/chocolateyInstall.ps1 create mode 100644 automatic/nexus-repository-migrator/tools/chocolateyUninstall.ps1 create mode 100644 automatic/nexus-repository-migrator/update.ps1 diff --git a/automatic/nexus-repository-migrator/nexus-repository-migrator.nuspec b/automatic/nexus-repository-migrator/nexus-repository-migrator.nuspec new file mode 100644 index 000000000000..bf44656b0097 --- /dev/null +++ b/automatic/nexus-repository-migrator/nexus-repository-migrator.nuspec @@ -0,0 +1,78 @@ + + + + nexus-repository-migrator + Nexus Repository Migrator + 3.70.1.3 + Sonatype + chocolatey-community, jpruskin + Migrator for the Sonatype Nexus Repository database. + + https://help.sonatype.com/en/orientdb-downloads.html + https://github.com/sonatype/nexus-public + https://help.sonatype.com/en/migrating-to-a-new-database.html + nexus-repository migration sonatype nexus + Sonatype + http://www.eclipse.org/legal/epl-v10.html + false + https://cdn.jsdelivr.net/gh/chocolatey-community/chocolatey-packages@f459e946d7b1926ee89c2b415ec8507dffe99218/icons/nexus-repository.png + https://help.sonatype.com/repomanager3/release-notes + + + + + + + + + diff --git a/automatic/nexus-repository-migrator/tools/ConvertFrom-NexusOrientDb.ps1 b/automatic/nexus-repository-migrator/tools/ConvertFrom-NexusOrientDb.ps1 new file mode 100644 index 000000000000..5fd2a310a475 --- /dev/null +++ b/automatic/nexus-repository-migrator/tools/ConvertFrom-NexusOrientDb.ps1 @@ -0,0 +1,128 @@ +<# + .Synopsis + Migrates Sonatype Nexus Repository 3.70.1-02 to the H2 database type + + .Example + .\ConvertFrom-NexusOrientDb.ps1 + + .Example + .\ConvertFrom-NexusOrientDb.ps1 -JavaPath .\path\to\java.exe +#> +[CmdletBinding(SupportsShouldProcess)] +param( + [string]$JavaPath, + + [switch]$Force +) + +Import-Module $PSScriptRoot\nexus-helpers.ps1 -Verbose:$false + +foreach ($Service in Get-NexusRepositoryServiceInstall) { + if ($Force -or (Test-NexusMigratorRequired -DataDir (Split-Path $Service.DataFolder) -ProgramDir $Service.ProgramFolder)) { + Write-Host "Preparing for database migration..." + $MigrationFiles = Join-Path $env:Temp "dbmigration-$($Service.ServiceName)" + $PreMigrationIssues = @() + + if (Test-NexusMigratorFreeSpaceProblem -Drive $MigrationFiles.Split(':')[0] -DatabaseFolder (Join-Path $Service.DataFolder "db")) { + $PreMigrationIssues += "Cannot migrate database with available disk space" + } + + if (Test-NexusMigratorMemoryProblem) { + $PreMigrationIssues += "Cannot migrate database with available memory" + } + + # Test if contained JRE is compatible, otherwise check JAVA_HOME, otherwise... + $JavaPath = @( + $JavaPath + Join-Path $Service.ProgramFolder "\jre\bin\java.exe" + Convert-Path $env:JAVA_HOME\bin\java.exe + Convert-Path $env:ProgramFiles\*\jre-*\bin\java.exe + ) | Where-Object { + $_ -and + (Test-Path $_) -and + (([version](Get-ItemProperty -Path $_).VersionInfo.ProductVersion).Major -in 8, 11) + } | Select-Object -First 1 + + if (-not $JavaPath) { + $PreMigrationIssues += "Nexus Migrator requires JRE 8 or JRE 11. Please provide a -JavaPath to a compatible version." + } + + # See: https://help.sonatype.com/en/orientdb-downloads.html + $MigratorDownload = @{ + Url = 'https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-3.70.1-03.jar' + FileFullPath = Join-Path $PSScriptRoot "nexus-db-migrator.jar" + Checksum = "02ea88e88e7d5d7f9d8a1738c9c0363fde636fc22e295efddf9d0f5e7bed982a" + ChecksumType = "SHA256" + } + if (-not (Test-Path $MigratorDownload.FileFullPath)) { + $ProgressPreference, $CurrentProgressPreference = "SilentlyContinue", $ProgressPreference + try { + Invoke-WebRequest -Uri $MigratorDownload.Url -OutFile $MigratorDownload.FileFullPath -UseBasicParsing + } finally { + $ProgressPreference = $CurrentProgressPreference + } + } + + $MigratorHash = Get-FileHash -Path $MigratorDownload.FileFullPath -Algorithm $MigratorDownload.ChecksumType + if ($MigratorHash.Hash -ne $MigratorDownload.Checksum) { + $PreMigrationIssues += "The hash of the downloaded file '$($MigratorDownload.Url | Split-Path -Leaf)' ('$($MigratorHash.Hash)') did not match the expected hash ('$($MigratorDownload.Checksum)')." + } + + if ($PreMigrationIssues) { + Write-Error -Message ($PreMigrationIssues -join "`n") -ErrorAction Stop + } + + $ServiceState = (Get-Service $Service.ServiceName).Status + + New-NexusOrientDbBackup -DataDir (Split-Path $Service.DataFolder) -ServiceName $Service.ServiceName -DestinationPath $MigrationFiles + + try { + Push-Location $MigrationFiles + Write-Host "Migrating database from 'OrientDb' to 'H2'" + # We could adjust the memory values to work on more systems, + # but these are the recommended arguments from Sonatype. + $JavaArgs = @( + "-Xmx16G" + "-Xms16G" + "-XX:+UseG1GC" + "-XX:MaxDirectMemorySize=28672M" + "-jar" + $MigratorDownload.FileFullPath + "--migration_type=h2" + "--yes" + ) + & $JavaPath @JavaArgs + + if ($LASTEXITCODE -ne 0) { + throw "Migration of the database failed." + } + + if ($PSCmdlet.ShouldProcess("$MigrationFiles\nexus.mv.db", "Moving migrated database")) { + Copy-Item -Path $MigrationFiles\nexus.mv.db -Destination (Join-Path $Service.DataFolder "db") + } + $NexusConfigFile = Join-Path $Service.DataFolder "etc\nexus.properties" + if ((Get-NexusConfiguration -Path $NexusConfigFile).'nexus.datastore.enabled' -ne 'true' -and $PSCmdlet.ShouldProcess($NexusConfigFile, 'Updating Datastore Configuration')) { + (Get-Content $NexusConfigFile) | Where-Object {$_ -notmatch '^\W*nexus\.datastore\.enabled='} | Set-Content $NexusConfigFile + Add-Content -Path $NexusConfigFile -Value "nexus.datastore.enabled=true" + } + + if ($ServiceState -eq 'Running') { + try { + Write-Host "Restarting '$($Service.ServiceName)'" + Restart-Service $Service.ServiceName + Wait-NexusAvailability -Hostname $Hostname -Config $NexusConfigFile -ErrorAction Stop + } catch { + Write-Error -Message (@( + "The Nexus service '$($Service.ServiceName)' was restarted, but did not recover." + "Check the logs at '$(Join-Path $Service.DataFolder "log")'" + ) -join "`n") + } + } + } finally { + Pop-Location + Remove-Item $MigrationFiles -Recurse + } + } else { + Write-Warning "'$($Service.DataFolder)' was not migrated" + } +} \ No newline at end of file diff --git a/automatic/nexus-repository-migrator/tools/Repair-Nexus371FailedUpgrade.ps1 b/automatic/nexus-repository-migrator/tools/Repair-Nexus371FailedUpgrade.ps1 new file mode 100644 index 000000000000..1e291227b89d --- /dev/null +++ b/automatic/nexus-repository-migrator/tools/Repair-Nexus371FailedUpgrade.ps1 @@ -0,0 +1,91 @@ +<# + .Synopsis + Repairs a broken upgrade of Sonatype Nexus Repository OSS + + .Example + .\Repair-Nexus371FailedUpgrade.ps1 + # Repairs the Nexus install, ending with a migrated database and version 3.71.0.6 + + .Example + .\Repair-Nexus371FailedUpgrade.ps1 -Rollback + # Repairs the Nexus install, ending with an unmodified database and version 3.70.1.2 +#> +[CmdletBinding(DefaultParameterSetName="Upgrade")] +param( + # If selected, rolls the install back to 3.70.x instead of upgrading. + [Parameter(ParameterSetName="Repair")] + [Alias("Repair")] + [switch]$Rollback, + + # Temporary Path for extracting files + [string]$ExtractPath = (Join-Path $env:Temp "nexus") +) +$ProgressPreference = "SilentlyContinue" +$ErrorActionPreference = "Stop" + +Import-Module $PSScriptRoot\nexus-helpers.ps1 -Verbose:$false + +# Test if Nexus JRE matches +$JavaPath = @( + Join-Path $env:ProgramData "\nexus\jre\bin\java.exe" + Convert-Path $env:JAVA_HOME\bin\java.exe + Convert-Path $env:ProgramFiles\*\jre-*\bin\java.exe +) | Where-Object { + $_ -and + (Test-Path $_) -and + (([version](Get-ItemProperty -Path $_).VersionInfo.ProductVersion).Major -in 8, 11) +} | Select-Object -First 1 + +# Download Java if it's missing, via the old version of Nexus Repository +if (-not $JavaPath -and -not ($JavaPath = Convert-Path "$ExtractPath\nexus-3.70.1-02\jre\bin\java.exe" -ErrorAction SilentlyContinue)) { + Invoke-WebRequest -Uri https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/3/nexus-3.70.1-02-win64.zip -OutFile "$env:Temp\nexus-3.70.1-02.zip" + Expand-Archive -Path "$env:Temp\nexus-3.70.1-02.zip" -DestinationPath $ExtractPath + $JavaPath = Convert-Path "$ExtractPath\nexus-3.70.1-02\jre\bin\java.exe" + Remove-Item "$env:Temp\nexus-3.70.1-02.zip" +} + +$BackupLocation = "$PSScriptRoot\$(New-Guid)" +Backup-NexusSSL -BackupLocation $BackupLocation + +# Get the "installed" and package version of Nexus +$NexusVersion = Get-NexusVersion +$null = [System.Reflection.Assembly]::LoadFrom("$env:ChocolateyInstall\choco.exe") +$LatestPackageVersion = [Chocolatey.NugetVersionExtensions]::ToNormalizedStringChecked( + "$($NexusVersion -replace '-','.')" +) + +if ((Get-Service nexus).Status -ne 'running') { + if ($PSCmdlet.ParameterSetName -eq 'Upgrade') { + & $PSScriptRoot\ConvertFrom-NexusOrientDb.ps1 -JavaPath $JavaPath -Force + } + + # The combined installation of old and new Nexus Java versions and supports + # causes the install to become un-startable. We'll replace it. + Remove-Item $env:ProgramData\nexus -Recurse + + switch ($PSCmdlet.ParameterSetName) { + "Repair" { + Copy-Item -Path "$ExtractPath\nexus-3.70.1-02\" -Destination "$env:ProgramData\nexus" -Recurse + } + "Upgrade" { + # Download the matching version of Nexus + Invoke-WebRequest -Uri https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/3/nexus-$($NexusVersion)-win64.zip -OutFile "$env:Temp\nexus-$($NexusVersion)-win64.zip" + Expand-Archive -Path "$env:Temp\nexus-$($NexusVersion)-win64.zip" -DestinationPath $ExtractPath -Force + Copy-Item -Path "$ExtractPath\nexus-$NexusVersion\" -Destination "$env:ProgramData\nexus" -Recurse + Remove-Item "$env:Temp\nexus-$($NexusVersion)-win64.zip" + + # Ensure the package is in a good state, from CCR as we know the local repository isn't running. + choco upgrade nexus-repository --version $LatestPackageVersion --confirm --no-progress --source https://community.chocolatey.org/api/v2/ --skip-powershell + } + } +} else { + Write-Warning "The service is already running. You don't need to repair." +} + +try { + Restore-NexusSSL -BackupLocation $BackupLocation +} finally { + Remove-Item $BackupLocation -Recurse +} + +Restart-Service nexus \ No newline at end of file diff --git a/automatic/nexus-repository-migrator/tools/chocolateyInstall.ps1 b/automatic/nexus-repository-migrator/tools/chocolateyInstall.ps1 new file mode 100644 index 000000000000..b02da563c3ab --- /dev/null +++ b/automatic/nexus-repository-migrator/tools/chocolateyInstall.ps1 @@ -0,0 +1,23 @@ +$ErrorActionPreference = 'Stop' +$toolsDir = Split-Path $MyInvocation.MyCommand.Definition +$PackageParameters = Get-PackageParameters + +$MigratorDownload = @{ + PackageName = $env:ChocolateyPackageName + Url = 'https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-3.70.1-03.jar' + FileFullPath = Join-Path $toolsDir "nexus-db-migrator.jar" + Checksum = '02ea88e88e7d5d7f9d8a1738c9c0363fde636fc22e295efddf9d0f5e7bed982a' + ChecksumType = 'SHA256' +} +Get-ChocolateyWebFile @MigratorDownload + +$PowerShellScript = @{ + packageName = $env:ChocolateyPackageName + PsFileFullPath = Join-Path $toolsDir "ConvertFrom-NexusOrientDb.ps1" +} +Install-ChocolateyPowershellCommand @PowerShellScript + +if ($PackageParameters.AttemptMigration) { + & $toolsDir\ConvertFrom-NexusOrientDb.ps1 -ErrorAction Stop + Write-Host "You may now uninstall this package with 'choco uninstall $($env:ChocolateyPackageName) --confirm'." +} diff --git a/automatic/nexus-repository-migrator/tools/chocolateyUninstall.ps1 b/automatic/nexus-repository-migrator/tools/chocolateyUninstall.ps1 new file mode 100644 index 000000000000..53ebbdd72dc1 --- /dev/null +++ b/automatic/nexus-repository-migrator/tools/chocolateyUninstall.ps1 @@ -0,0 +1,4 @@ +$ErrorActionPreference = 'Stop' +$toolsDir = Split-Path $MyInvocation.MyCommand.Definition + +Uninstall-BinFile -Name "ConvertFrom-NexusOrientDb" -Path $toolsDir\ConvertFrom-NexusOrientDb.ps1 \ No newline at end of file diff --git a/automatic/nexus-repository-migrator/update.ps1 b/automatic/nexus-repository-migrator/update.ps1 new file mode 100644 index 000000000000..5061d336b947 --- /dev/null +++ b/automatic/nexus-repository-migrator/update.ps1 @@ -0,0 +1,39 @@ +Import-Module Chocolatey-AU + +function global:au_GetLatest { + $R = Invoke-WebRequest -Uri https://help.sonatype.com/en/orientdb-downloads.html -UseBasicParsing + $MigratorUrl = $R.Links.href | Where-Object { + $_ -like 'https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-3.70.*.jar' + } + + if ($MigratorUrl.Count -ne 1) { + throw "Found $($MigratorUrl.Count) URLs that look like the migrator:`n $($MigratorUrl -join "`n ")" + } + + if ($MigratorUrl -match "/nexus-db-migrator-(?3\.70\.\d+-\d+)\.jar$") { + $NexusMigratorVersion = $Matches.Version + } + + $null = [System.Reflection.Assembly]::LoadFrom("$env:ChocolateyInstall\choco.exe") + $LatestPackageVersion = [Chocolatey.NugetVersionExtensions]::ToNormalizedStringChecked( + "$($NexusMigratorVersion -replace '-','.')" + ) + + @{ + NexusVersion = $NexusMigratorVersion + Version = $LatestPackageVersion + URL = $MigratorUrl + SHA256 = (Invoke-RestMethod "$MigratorUrl.sha256" -UseBasicParsing).Trim() + } +} + +function global:au_SearchReplace { + @{ + ".\tools\chocolateyInstall.ps1" = @{ + "(^\s*url\s*=\s*)('.*')" = "`$1'$($Latest.URL)'" + "(^\s*checksum\s*=\s*)('.*')" = "`$1'$($Latest.SHA256)'" + } + } +} + +update -ChecksumFor none \ No newline at end of file diff --git a/automatic/nexus-repository/tools/chocolateyinstall.ps1 b/automatic/nexus-repository/tools/chocolateyinstall.ps1 index 487a7948d080..6c3e664b2190 100644 --- a/automatic/nexus-repository/tools/chocolateyinstall.ps1 +++ b/automatic/nexus-repository/tools/chocolateyinstall.ps1 @@ -56,60 +56,11 @@ if ($pp.ContainsKey("BackupSslConfig") -or $CurrentConfig.'application-port-ssl' } if (Test-NexusMigratorRequired -DataDir $TargetDataFolder -ProgramDir $TargetFolder) { - Write-Host "Preparing for database migration..." - $MigrationFiles = Join-Path $ExtractFolder "dbmigration" - - if (Test-NexusMigratorFreeSpaceProblem -Drive $MigrationFiles.Split(':')[0] -DatabaseFolder $TargetDataFolder\nexus3\db) { - throw "Cannot migrate database with available disk space" - } - - if (Test-NexusMigratorMemoryProblem) { - throw "Cannot migrate database with available memory" - } - - New-NexusOrientDbBackup -DataDir $TargetDataFolder -ServiceName $ServiceName -DestinationPath $MigrationFiles - - # See: https://help.sonatype.com/en/orientdb-downloads.html - $MigratorDownload = @{ - PackageName = $env:ChocolateyPackageName - Url = 'https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-3.70.1-03.jar' - FileFullPath = Join-Path $toolsDir "nexus-db-migrator.jar" - Checksum = "02ea88e88e7d5d7f9d8a1738c9c0363fde636fc22e295efddf9d0f5e7bed982a" - ChecksumType = "SHA256" - } - Get-ChocolateyWebFile @MigratorDownload - - try { - Push-Location $MigrationFiles - Write-Host "Migrating database from 'OrientDb' to 'H2'" - $JavaPath = Join-Path $TargetFolder "jre/bin/java.exe" - $JavaArgs = @( - "-Xmx16G" - "-Xms16G" - "-XX:+UseG1GC" - "-XX:MaxDirectMemorySize=28672M" - "-jar" - $MigratorDownload.FileFullPath - "--migration_type=h2" - "--yes" - ) - & $JavaPath @JavaArgs - - if ($LASTEXITCODE -ne 0) { - throw "Migration of the database failed." - } - - Copy-Item -Path $MigrationFiles\nexus.mv.db -Destination $TargetDataFolder\nexus3\db\ - if ((Get-NexusConfiguration).'nexus.datastore.enabled' -ne 'true') { - (Get-Content $NexusConfigFile) | Where-Object {$_ -notmatch '^\W*nexus\.datastore\.enabled='} | Set-Content $NexusConfigFile - Add-Content -Path $NexusConfigFile -Value "nexus.datastore.enabled=true" - } - - Remove-Item "$TargetFolder" -Recurse # This particular upgrade has more overlap than previous ones - } finally { - Pop-Location - Remove-Item $MigrationFiles -Recurse - } + Write-Error (@( + "This upgrade will fail if you do not migrate your database from OrientDb before proceeding." + "You can do this with the nexus-repository-migrator package, or following the upgrade instructions." + "For more details, please see: https://help.sonatype.com/en/orient-3-70-java-8-or-11.html" + ) -join "`n") } # Extract the Nexus program files, and overwrite any previous program files diff --git a/automatic/nexus-repository/tools/helpers.ps1 b/automatic/nexus-repository/tools/helpers.ps1 index d5259eef1ebc..05b4e028e4b6 100644 --- a/automatic/nexus-repository/tools/helpers.ps1 +++ b/automatic/nexus-repository/tools/helpers.ps1 @@ -6,7 +6,6 @@ function Backup-NexusSSL { ) begin { if (-not (Test-Path $BackupLocation)) { - Write-Host "Creating SSL Backup location" $null = New-Item $BackupLocation -ItemType Directory } } @@ -39,47 +38,114 @@ function Restore-NexusSSL { if (Test-Path "$BackupLocation\jetty-https.xml") { Copy-Item "$BackupLocation\jetty-https.xml" "$env:ProgramData\nexus\etc\jetty" } - - Write-Host "Nexus is now available with the restored SSL configuration" } } -function Wait-NexusAvailability { +function Get-NexusCertificateDomain { param( - [Parameter(Mandatory = $true)] - [string]$Hostname, + [string]$DataDir = (Join-Path $env:ProgramData "sonatype-work"), - [Parameter(Mandatory)] - [Alias("Config")] - [string]$NexusConfigFile = (Join-Path $env:ProgramData "\sonatype-work\nexus3\etc\nexus.properties") + [string]$ProgramDir = (Join-Path $env:ProgramData "nexus") ) - # As the service is started, this should be present momentarily - $Timer = [System.Diagnostics.Stopwatch]::StartNew() - while (-not ($ConfigPresent = Test-Path $NexusConfigFile) -and $Timer.Elapsed.TotalSeconds -le 60) { - Write-Verbose "Waiting for '$($NexusConfigFile)' to become available ($($Timer.Elapsed.TotalSeconds) seconds waited)..." - Start-Sleep -Seconds 5 + $Config = Get-NexusConfiguration -Path $DataDir\nexus3\etc\nexus.properties + if ($Config.'nexus-args'.Split(',') -contains '${jetty.etc}/jetty-https.xml') { + [xml]$HttpsConfig = Get-Content $ProgramDir\etc\jetty\jetty-https.xml + $KeyToolPath = Join-Path $ProgramDir "jre/bin/keytool.exe" + $KeyStorePath = Join-Path (Join-Path $ProgramDir "etc/ssl") $HttpsConfig.SelectSingleNode("//Set[@name='KeyStorePath']").'#text' + $KeyStorePassword = $HttpsConfig.SelectSingleNode("//Set[@name='KeyStorePassword']").'#text' + + if ((Test-Path $KeyToolPath) -and (Test-Path $KeyStorePath)) { + # Running in a job, as otherwise KeyTool fails when run without input + Start-Job { + $KeyToolOutput = $using:KeyStorePassword | & "$using:KeyToolPath" -list -v -keystore "$using:KeyStorePath" -J"-Duser.language=en" 2>$null + if ($KeyToolOutput -join "`n" -match "(?smi)Certificate\[1\]:\nOwner: CN=(?.+?)\n") { + $Matches.Domain + } + } | Receive-Job -Wait + } } +} + +function Get-NexusUri { + param( + [Parameter()] + [string]$DataDir = (Join-Path $env:ProgramData "sonatype-work"), + + [Parameter()] + [string]$ProgramDir = (Join-Path $env:ProgramData "nexus"), + + [Parameter()] + [string]$ConfigPath = $( + if (Test-Path $DataDir/nexus3/etc/nexus.properties) { + "$DataDir/nexus3/etc/nexus.properties" + } elseif (Test-Path $ProgramDir/etc/nexus-default.properties) { + "$ProgramDir/etc/nexus-default.properties" + } + ), - $nexusScheme, $nexusPort, $nexusPath = if ($ConfigPresent) { - $Config = Get-NexusConfiguration -Path $NexusConfigFile + [string]$HostnameOverride + ) + $Scheme, $Hostname, $Port, $Path = if (Test-Path $ConfigPath) { + $Config = Get-NexusConfiguration -Path $ConfigPath -ErrorAction SilentlyContinue if ($Config.'application-port-ssl' -gt 0) { # This is to combat Package Internalizer's over-enthusiastic URL matching ('http' + 's') + if ($CertDomain = Get-NexusCertificateDomain -ConfigPath $ConfigPath) { + if (-not $script:OverriddenDomains) {$script:OverriddenDomains = @{}} + if ($CertDomain -notmatch '^\*') { + $CertDomain + } elseif ($CertDomain -match '^\*' -and $HostnameOverride -like $CertDomain) { + ($script:OverriddenDomains[$CertDomain] = $HostnameOverride) + } elseif ($CertDomain -match '^\*') { + while ($script:OverriddenDomains[$CertDomain] -notlike $CertDomain) { + $script:OverriddenDomains[$CertDomain] = Read-Host "Please provide the FQDN for Nexus matching the '$($CertDomain)' certificate" + } + $script:OverriddenDomains[$CertDomain] + } + } else { + Write-Warning "Could not figure out SSL configuration for $($env:ComputerName)" + $env:ComputerName + } $Config.'application-port-ssl' } elseif ($Config.'application-port' -gt 0) { 'http' + if ($HostnameOverride) { + $HostnameOverride + } else { + "localhost" + } $Config.'application-port' } $Config.'nexus-context-path' } - # Set defaults if not present - if (-not $nexusScheme) {$nexusScheme = 'http'} - if (-not $nexusPort) {$nexusPort = '8081'} + # Set defaults if still not present + if (-not $Hostname) {$Hostname = "localhost"} + if (-not $Scheme) {$Scheme = 'http'} + if (-not $Port) {$Port = '8081'} - $NexusUri = "$($nexusScheme)://$($Hostname):$($nexusPort)$($nexusPath)" + "$($Scheme)://$($Hostname):$($Port)$($Path)" +} + +function Wait-NexusAvailability { + param( + [Parameter()] + [string]$Hostname, + + [Parameter(Mandatory)] + [Alias("Config")] + [string]$NexusConfigFile = (Join-Path $env:ProgramData "\sonatype-work\nexus3\etc\nexus.properties") + ) + # As the service is started, this should be present momentarily + $Timer = [System.Diagnostics.Stopwatch]::StartNew() + while (-not ($ConfigPresent = Test-Path $NexusConfigFile) -and $Timer.Elapsed.TotalSeconds -le 60) { + Write-Verbose "Waiting for '$($NexusConfigFile)' to become available ($($Timer.Elapsed.TotalSeconds) seconds waited)..." + Start-Sleep -Seconds 5 + } + + $NexusUri = Get-NexusUri -Hostname $Hostname Write-Host "Waiting on Nexus Web UI to be available at '$($NexusUri)'" while ($Response.StatusCode -ne '200' -and $Timer.Elapsed.TotalMinutes -lt 3) { @@ -318,12 +384,15 @@ function Test-NexusMigratorRequired { Write-Error (@( "Please upgrade nexus-repository to version 3.70.1-02 before upgrading further." "You can do this by running 'choco upgrade nexus-repository --version 3.70.1.2 --confirm'" + "You will then need to migrate your database from OrientDb to H2 or PostgreSQL." "For more details, please see: https://help.sonatype.com/en/orient-pre-3-70-java-8-or-11.html" ) -join "`n") - throw "Package cannot upgrade from '$($CurrentVersion)' to '$($env:ChocolateyPackageVersion)'" + throw "Package cannot upgrade from '$($CurrentVersion)'" } elseif ($CurrentDeNexusVersion -eq $RequiredVersion) { # We will upgrade if we are on OrientDb, otherwise leave it alone. Test-NexusDatabaseType -Type "OrientDb" -DataDir $DataDir -ProgramDir $ProgramDir + } elseif ($CurrentDeNexusVersion -gt $RequiredVersion) { + Write-Verbose "Detected Nexus version '$($CurrentVersion)'. Will not attempt to upgrade." } } } @@ -411,4 +480,40 @@ function Test-NexusMigratorMemoryProblem { } return $Result +} + +function Get-NexusRepositoryServiceInstall { + <# + .Synopsis + If found, returns the name of the Nexus service and the install and data directories it uses. + + .Example + Get-NexusRepositoryInstallValues + #> + [CmdletBinding()] + param( + # By default, we assume there is only one service. This searches for all installed services. + [switch]$AllResults + ) + # If you have a lot of services, searching them all may take longer - + # so we can stop searching when we find the first service matching nexus.exe. + $ResultCount = @{} + if (-not $AllResults) {$ResultCount.First = 1} + + $NexusService = Get-ChildItem HKLM:\System\CurrentControlSet\Services\ | Where-Object { + ($ImagePath = Get-ItemProperty -Path $_.PSPath -Name ImagePath -ErrorAction SilentlyContinue) -and + $ImagePath.ImagePath.Trim('"''').EndsWith('\nexus.exe') + } | Select-Object @ResultCount + + foreach ($Service in $NexusService) { + $ServiceName = $Service.PSChildName + $TargetFolder = (Get-ItemProperty -Path $Service.PSPath).ImagePath.Trim('"''') | Split-Path | Split-Path + $DataFolder = Convert-Path (Join-Path $TargetFolder "$((Get-Content $TargetFolder\bin\nexus.vmoptions) -match '^-Dkaraf.data=(?.+)$' -replace '^-Dkaraf.data=')") + [PSCustomObject]@{ + ServiceName = $ServiceName + ProgramFolder = $TargetFolder + DataFolder = $DataFolder + Endpoint = Get-NexusUri -DataDir (Split-Path $DataFolder) -ProgramDir $TargetFolder + } + } } \ No newline at end of file