├── DockerMsftProvider.psd1 ├── DockerMsftProvider.psm1 ├── Json.coreclr.dll ├── LICENSE └── README.md /DockerMsftProvider.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'DockerMsftProvider' 3 | # 4 | # Generated by: jayshah 5 | # 6 | # Generated on: 08/12/2016 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | RootModule = 'DockerMsftProvider.psm1' 13 | 14 | # Version number of this module. 15 | ModuleVersion = '1.0.0.8' 16 | 17 | # ID used to uniquely identify this module 18 | GUID = '5beed3da-526b-47eb-9197-29c6a7214e4e' 19 | 20 | # Author of this module 21 | Author = 'jayshah' 22 | 23 | # Company or vendor of this module 24 | CompanyName = 'Microsoft' 25 | 26 | # Copyright statement for this module 27 | Copyright = '(c) 2016 Microsoft. All rights reserved.' 28 | 29 | # Description of the functionality provided by this module 30 | Description = 'PowerShell module with commands for discovering, installing, and updating Docker images.' 31 | 32 | # Minimum version of the Windows PowerShell engine required by this module 33 | PowerShellVersion = '5.1' 34 | 35 | # Functions to export from this module 36 | FunctionsToExport = @() 37 | 38 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 39 | PrivateData = @{ 40 | "PackageManagementProviders" = 'DockerMsftProvider.psm1' 41 | 42 | PSData = @{ 43 | # Tags applied to this module. These help with module discovery in online galleries. 44 | Tags = @('PackageManagement', 'Provider') 45 | ProjectUri = 'https://github.com/OneGet/MicrosoftDockerProvider' 46 | LicenseUri = 'https://github.com/OneGet/MicrosoftDockerProvider/blob/developer/LICENSE' 47 | ReleaseNotes = @' 48 | - Docker Provider to find, save and install docker on windows. 49 | '@ 50 | } # End of PSData hashtable 51 | 52 | } # End of PrivateData hashtable 53 | } 54 | -------------------------------------------------------------------------------- /DockerMsftProvider.psm1: -------------------------------------------------------------------------------- 1 | 2 | ######################################################################################### 3 | # 4 | # Copyright (c) Microsoft Corporation. All rights reserved. 5 | # 6 | # DockerMsftProvider 7 | # 8 | ######################################################################################### 9 | 10 | Microsoft.PowerShell.Core\Set-StrictMode -Version Latest 11 | 12 | #region variables 13 | 14 | $script:Providername = "DockerMsftProvider" 15 | $script:DockerSources = $null 16 | $script:location_modules = Microsoft.PowerShell.Management\Join-Path -Path $env:TEMP -ChildPath $script:ProviderName 17 | $script:location_sources= Microsoft.PowerShell.Management\Join-Path -Path $env:LOCALAPPDATA -ChildPath $script:ProviderName 18 | $script:file_modules = Microsoft.PowerShell.Management\Join-Path -Path $script:location_sources -ChildPath "sources.txt" 19 | $script:DockerSearchIndex = "DockerSearchIndex.json" 20 | $script:Installer_Extension = "zip" 21 | $script:dockerURL = "https://go.microsoft.com/fwlink/?LinkID=825636&clcid=0x409" 22 | $separator = "|#|" 23 | $script:restartRequired = $false 24 | $script:isNanoServerInitialized = $false 25 | $script:isNanoServer = $false 26 | $script:SystemEnvironmentKey = 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' 27 | $script:pathDockerRoot = Microsoft.PowerShell.Management\Join-Path -Path $env:ProgramFiles -ChildPath "Docker" 28 | $script:pathDockerD = Microsoft.PowerShell.Management\Join-Path -Path $script:pathDockerRoot -ChildPath "dockerd.exe" 29 | $script:pathDockerClient = Microsoft.PowerShell.Management\Join-Path -Path $script:pathDockerRoot -ChildPath "docker.exe" 30 | $script:wildcardOptions = [System.Management.Automation.WildcardOptions]::CultureInvariant -bor ` 31 | [System.Management.Automation.WildcardOptions]::IgnoreCase 32 | 33 | $script:NuGetProviderName = "NuGet" 34 | $script:NuGetBinaryProgramDataPath="$env:ProgramFiles\PackageManagement\ProviderAssemblies" 35 | $script:NuGetBinaryLocalAppDataPath="$env:LOCALAPPDATA\PackageManagement\ProviderAssemblies" 36 | $script:NuGetProvider = $null 37 | $script:nanoserverPackageProvider = "NanoServerPackage" 38 | $script:hotFixID = 'KB3176936' 39 | $script:minOsMajorBuild = 14393 40 | $script:minOSRevision= 206 41 | $script:MetadataFileName = 'metadata.json' 42 | $script:serviceName = "docker" 43 | $script:SemVerTypeName = 'Microsoft.PackageManagement.Provider.Utility.SemanticVersion' 44 | if('Microsoft.PackageManagement.NuGetProvider.SemanticVersion' -as [Type]) 45 | { 46 | $script:SemVerTypeName = 'Microsoft.PackageManagement.NuGetProvider.SemanticVersion' 47 | } 48 | 49 | #endregion variables 50 | 51 | #region One-Get Functions 52 | 53 | function Find-Package 54 | { 55 | [CmdletBinding()] 56 | param 57 | ( 58 | [string[]] 59 | $names, 60 | 61 | [string] 62 | $RequiredVersion, 63 | 64 | [string] 65 | $MinimumVersion, 66 | 67 | [string] 68 | $MaximumVersion 69 | ) 70 | 71 | Set-ModuleSourcesVariable 72 | $null = Install-NuGetClientBinary -CallerPSCmdlet $PSCmdlet 73 | 74 | $options = $request.Options 75 | 76 | foreach( $o in $options.Keys ) 77 | { 78 | Write-Debug ( "OPTION: {0} => {1}" -f ($o, $options[$o]) ) 79 | } 80 | 81 | $AllVersions = $null 82 | if($options.ContainsKey("AllVersions")) 83 | { 84 | $AllVersions = $options['AllVersions'] 85 | } 86 | 87 | $sources = @() 88 | if($options.ContainsKey('Source')) 89 | { 90 | $sources = $options['Source'] 91 | } 92 | 93 | if ((-not $names) -or ($names.Count -eq 0)) 94 | { 95 | $names = @('') 96 | } 97 | 98 | $allResults = @() 99 | $allSources = Get-SourceList -Sources $sources 100 | 101 | foreach($currSource in $allSources) 102 | { 103 | $Location = $currSource.SourceLocation 104 | $sourceName = $currSource.Name 105 | 106 | if($location.StartsWith("https://")) 107 | { 108 | $tempResults = @() 109 | $tempResults += Find-FromUrl -Source $Location ` 110 | -SourceName $sourceName ` 111 | -Name $names ` 112 | -MinimumVersion $MinimumVersion ` 113 | -MaximumVersion $MaximumVersion ` 114 | -RequiredVersion $RequiredVersion ` 115 | -AllVersions:$AllVersions 116 | 117 | if($tempResults) 118 | { 119 | $allResults += $tempResults 120 | } 121 | } 122 | else 123 | { 124 | Write-Error "Currently only https sources are supported. Please register with https source." 125 | } 126 | } 127 | 128 | if((-not $allResults) -or ($allResults.Count -eq 0)) 129 | { 130 | return 131 | } 132 | 133 | foreach($result in $allResults) 134 | { 135 | $swid = New-SoftwareIdentityFromDockerInfo -DockerInfo $result 136 | Write-Output $swid 137 | } 138 | } 139 | 140 | function Download-Package 141 | { 142 | [CmdletBinding()] 143 | param 144 | ( 145 | [Parameter(Mandatory=$true)] 146 | [ValidateNotNullOrEmpty()] 147 | [string] 148 | $FastPackageReference, 149 | 150 | [Parameter(Mandatory=$true)] 151 | [ValidateNotNullOrEmpty()] 152 | [string] 153 | $Location 154 | ) 155 | 156 | DownloadPackageHelper -FastPackageReference $FastPackageReference ` 157 | -Request $Request ` 158 | -Location $Location 159 | } 160 | 161 | function Install-Package 162 | { 163 | [CmdletBinding()] 164 | param 165 | ( 166 | [Parameter(Mandatory=$true)] 167 | [ValidateNotNullOrEmpty()] 168 | [string] 169 | $fastPackageReference 170 | ) 171 | 172 | if(-not (Test-AdminPrivilege)) 173 | { 174 | ThrowError -CallerPSCmdlet $PSCmdlet ` 175 | -ExceptionName "InvalidOperationException" ` 176 | -ExceptionMessage "Administrator rights are required to install docker." ` 177 | -ErrorId "AdminPrivilegesAreRequiredForInstall" ` 178 | -ErrorCategory InvalidOperation 179 | } 180 | 181 | if(-not (IsNanoServer)) 182 | { 183 | $osVersion = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\').CurrentBuildNumber 184 | $osRevision = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\').UBR 185 | # Ensure that the host is either running a build newer than Windows Server 2016 GA or 186 | # if running Windows Server 2016 GA that it has a revision greater than 206 (KB3176936) 187 | if (($osVersion -lt $script:minOsMajorBuild) -or 188 | (($osVersion -eq $script:minOsMajorBuild) -and ($osRevision -lt $script:minOsRevision))) 189 | { 190 | ThrowError -CallerPSCmdlet $PSCmdlet ` 191 | -ExceptionName "InvalidOperationException" ` 192 | -ExceptionMessage "$script:hotFixID or later is required for docker to work" ` 193 | -ErrorId "RequiredWindowsUpdateNotInstalled" ` 194 | -ErrorCategory InvalidOperation 195 | return 196 | } 197 | 198 | # This block should not be removed. It enforces Docker's support policy towards which 199 | # SKU of Windows that Docker Engine - Enterprise is supported on. Windows 10 users should 200 | # use Docker Desktop for Windows instead. 201 | if ((Get-CimInstance Win32_Operatingsystem | Select-Object -expand Caption) -like "*Windows 10*") 202 | { 203 | ThrowError -CallerPSCmdlet $PSCmdlet ` 204 | -ExceptionName "InvalidOperationException" ` 205 | -ExceptionMessage "Docker Engine - Enterprise is not supported on Windows 10 client. See https://aka.ms/docker-for-windows instead." ` 206 | -ErrorId "RequiresWindowsServer" ` 207 | -ErrorCategory InvalidOperation 208 | return 209 | } 210 | } 211 | else 212 | { 213 | Write-Warning "$script:hotFixID or later is required for docker to work. Please ensure this is installed." 214 | } 215 | 216 | $options = $request.Options 217 | $update = $false 218 | $force = $false 219 | 220 | if($options) 221 | { 222 | foreach( $o in $options.Keys ) 223 | { 224 | Write-Debug ("OPTION: {0} => {1}" -f ($o, $request.Options[$o]) ) 225 | } 226 | 227 | if($options.ContainsKey('Update')) 228 | { 229 | Write-Verbose "Updating the docker installation." 230 | $update = $true 231 | } 232 | 233 | if($options.ContainsKey("Force")) 234 | { 235 | $force = $true 236 | } 237 | } 238 | 239 | if(Test-Path $script:pathDockerD) 240 | { 241 | if($update -or $force) 242 | { 243 | # Uninstall if another installation exists 244 | UninstallHelper 245 | } 246 | elseif(-not $force) 247 | { 248 | $dockerVersion = & "$script:pathDockerClient" --version 249 | $resultArr = $dockerVersion -split "," 250 | $version = ($resultArr[0].Trim() -split " ")[2] 251 | 252 | Write-Verbose "Docker $version already exists. Skipping install. Use -force to install anyway." 253 | return 254 | } 255 | } 256 | else 257 | { 258 | # Install WindowsFeature containers 259 | try 260 | { 261 | InstallContainer 262 | } 263 | catch 264 | { 265 | $ErrorMessage = $_.Exception.Message 266 | ThrowError -CallerPSCmdlet $PSCmdlet ` 267 | -ExceptionName $_.Exception.GetType().FullName ` 268 | -ExceptionMessage $ErrorMessage ` 269 | -ErrorId FailedToDownload ` 270 | -ErrorCategory InvalidOperation 271 | 272 | return 273 | } 274 | } 275 | 276 | $splitterArray = @("$separator") 277 | $resultArray = $fastPackageReference.Split($splitterArray, [System.StringSplitOptions]::None) 278 | 279 | if((-not $resultArray) -or ($resultArray.count -ne 8)){Write-Debug "Fast package reference doesn't have required parts."} 280 | 281 | $source = $resultArray[0] 282 | $name = $resultArray[1] 283 | $version = $resultArray[2] 284 | $description = $resultArray[3] 285 | $originPath = $resultArray[5] 286 | $size = $resultArray[6] 287 | $sha = $resultArray[7] 288 | $date = $resultArray[4] 289 | $Location = $script:location_modules 290 | 291 | $destination = GenerateFullPath -Location $Location ` 292 | -Name $name ` 293 | -Version $Version 294 | 295 | $downloadOutput = DownloadPackageHelper -FastPackageReference $FastPackageReference ` 296 | -Request $Request ` 297 | -Location $Location 298 | 299 | if(-not (Test-Path $destination)) 300 | { 301 | Write-Error "$destination does not exist" 302 | return 303 | } 304 | else 305 | { 306 | Write-verbose "Found $destination to install." 307 | } 308 | 309 | # Install 310 | try 311 | { 312 | Write-Verbose "Trying to unzip : $destination" 313 | $null = Expand-Archive -Path $destination -DestinationPath $env:ProgramFiles -Force 314 | 315 | # Rename the docker folder to become Docker 316 | $dummyName = 'dummyName' 317 | $null = Rename-Item -Path $script:pathDockerRoot -NewName $env:ProgramFiles\$dummyName 318 | $null = Rename-Item -Path $env:ProgramFiles\$dummyName -NewName $script:pathDockerRoot 319 | 320 | if(Test-Path $script:pathDockerD) 321 | { 322 | Write-Verbose "Trying to enable the docker service..." 323 | $service = get-service -Name Docker -WarningAction SilentlyContinue -ErrorAction SilentlyContinue 324 | if(-not $service) 325 | { 326 | & "$script:pathDockerD" --register-service 327 | } 328 | } 329 | else 330 | { 331 | Write-Error "Unable to expand docker to Program Files." 332 | } 333 | } 334 | catch 335 | { 336 | $ErrorMessage = $_.Exception.Message 337 | ThrowError -CallerPSCmdlet $PSCmdlet ` 338 | -ExceptionName $_.Exception.GetType().FullName ` 339 | -ExceptionMessage $ErrorMessage ` 340 | -ErrorId FailedToDownload ` 341 | -ErrorCategory InvalidOperation 342 | } 343 | finally 344 | { 345 | # Clean up 346 | Write-Verbose "Removing the archive: $destination" 347 | $null = remove-item $destination -Force 348 | } 349 | 350 | # Save the install information 351 | $null = SaveInfo -Source $source 352 | 353 | # Update the path variable 354 | $null = Update-PathVar 355 | 356 | if($script:restartRequired) 357 | { 358 | Write-Warning "A restart is required to enable the containers feature. Please restart your machine." 359 | } 360 | 361 | Write-Warning "This provider is being deprecated and should no longer be used. Users should refer to the instructions on aka.ms/containers/install instead." 362 | 363 | Write-Output $downloadOutput 364 | } 365 | 366 | function Uninstall-Package 367 | { 368 | [CmdletBinding()] 369 | param 370 | ( 371 | [Parameter(Mandatory=$true)] 372 | [ValidateNotNullOrEmpty()] 373 | [string] 374 | $fastPackageReference 375 | ) 376 | 377 | UninstallHelper 378 | 379 | Write-Verbose "Uninstalling container feature from windows" 380 | UninstallContainer 381 | 382 | [string[]] $splitterArray = @("$separator") 383 | [string[]] $resultArray = $fastPackageReference.Split($splitterArray, [System.StringSplitOptions]::None) 384 | 385 | if((-not $resultArray) -or ($resultArray.count -ne 3)){Write-Debug "Fast package reference doesn't have required parts."} 386 | 387 | $name = $resultArray[0] 388 | $version = $resultArray[1] 389 | $source = $resultArray[2] 390 | 391 | $dockerSWID = @{ 392 | Name = $name 393 | version = $version 394 | Source = $source 395 | versionScheme = "MultiPartNumeric" 396 | fastPackageReference = $fastPackageReference 397 | } 398 | 399 | New-SoftwareIdentity @dockerSWID 400 | } 401 | 402 | #endregion One-Get Functions 403 | 404 | #region One-Get Required Functions 405 | 406 | function Initialize-Provider 407 | { 408 | write-debug "In $($script:Providername) - Initialize-Provider" 409 | } 410 | 411 | function Get-PackageProviderName 412 | { 413 | return $script:Providername 414 | } 415 | 416 | function Get-InstalledPackage 417 | { 418 | param 419 | ( 420 | [string]$name, 421 | [string]$requiredVersion, 422 | [string]$minimumVersion, 423 | [string]$maximumVersion 424 | ) 425 | 426 | $name = 'docker' 427 | $version = '' 428 | $source = '' 429 | 430 | if(Test-Path $script:pathDockerRoot\$script:MetadataFileName) 431 | { 432 | $metaContent = (Get-Content -Path $script:pathDockerRoot\$script:MetadataFileName) 433 | 434 | if(IsNanoServer) 435 | { 436 | $jsonDll = [Microsoft.PowerShell.CoreCLR.AssemblyExtensions]::LoadFrom($PSScriptRoot + "\Json.coreclr.dll") 437 | $jsonParser = $jsonDll.GetTypes() | Where-Object name -match jsonparser 438 | $metaContentParsed = $jsonParser::FromJson($metaContent) 439 | 440 | $source = if($metaContentParsed.ContainsKey('SourceName')) {$metaContentParsed.SourceName} else {'Unable To Retrieve Source from metadata.json'} 441 | $version = if($metaContentParsed.ContainsKey('Version')) {$metaContentParsed.Version} else {'Unable To Retrieve Version from metadata.json'} 442 | } 443 | else 444 | { 445 | $metaContentParsed = (Get-Content -Path $script:pathDockerRoot\$script:MetadataFileName) | ConvertFrom-Json 446 | if($metaContentParsed) 447 | { 448 | $source = if($metaContentParsed.PSObject.properties.name -contains 'SourceName') {$metaContentParsed.SourceName} else {'Unable To Retrieve Source from metadata.json'} 449 | $version = if($metaContentParsed.PSObject.properties.name -contains 'Version') {$metaContentParsed.Version} else {'Unable To Retrieve Version from metadata.json'} 450 | } 451 | } 452 | } 453 | elseif(Test-Path $script:pathDockerD) 454 | { 455 | $dockerVersion = & "$script:pathDockerClient" --version 456 | $resultArr = $dockerVersion -split "," 457 | $version = ($resultArr[0].Trim() -split " ")[2] 458 | $source = ' ' 459 | } 460 | else 461 | { 462 | return $null 463 | } 464 | 465 | $fastPackageReference = $name + 466 | $separator + $version + 467 | $separator + $source 468 | 469 | $dockerSWID = @{ 470 | Name = $name 471 | version = $version 472 | Source = $source 473 | versionScheme = "MultiPartNumeric" 474 | fastPackageReference = $fastPackageReference 475 | } 476 | 477 | return New-SoftwareIdentity @dockerSWID 478 | } 479 | 480 | #endregion One-Get Required Functions 481 | 482 | #region Helper-Functions 483 | 484 | function SaveInfo 485 | { 486 | param 487 | ( 488 | [Parameter(Mandatory=$true)] 489 | [ValidateNotNullOrEmpty()] 490 | [String] 491 | $Source 492 | ) 493 | 494 | # Create a file 495 | $metaFileInfo = New-Item -ItemType File -Path $script:pathDockerRoot -Name $script:MetadataFileName -Force 496 | 497 | if(-not $metaFileInfo) 498 | { 499 | # TODO: Handle File not created scenario 500 | } 501 | 502 | if(Test-Path $script:pathDockerD) 503 | { 504 | $dockerVersion = & "$script:pathDockerD" --version 505 | $resultArr = $dockerVersion -split "," 506 | $version = ($resultArr[0].Trim() -split " ")[2] 507 | 508 | $metaInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ 509 | SourceName = $source 510 | Version = $version 511 | }) 512 | 513 | $metaInfo | ConvertTo-Json > $metaFileInfo 514 | } 515 | } 516 | 517 | function UninstallHelper 518 | { 519 | if(-not (Test-AdminPrivilege)) 520 | { 521 | ThrowError -CallerPSCmdlet $PSCmdlet ` 522 | -ExceptionName "InvalidOperationException" ` 523 | -ExceptionMessage "Administrator rights are required to install docker." ` 524 | -ErrorId "AdminPrivilegesAreRequiredForInstall" ` 525 | -ErrorCategory InvalidOperation 526 | } 527 | 528 | # Stop docker service 529 | $dockerService = get-service -Name Docker -WarningAction SilentlyContinue -ErrorAction SilentlyContinue 530 | if(-not $dockerService) 531 | { 532 | # Docker service is not available 533 | Write-Warning "Docker Service is not available." 534 | } 535 | 536 | if(($dockerService.Status -eq "Started") -or ($dockerService.Status -eq "Running")) 537 | { 538 | Write-Verbose "Trying to stop docker service" 539 | $null = stop-service docker 540 | } 541 | 542 | if(Test-Path $script:pathDockerD) 543 | { 544 | Write-Verbose "Unregistering the docker service" 545 | $null = & "$script:pathDockerD" --unregister-service 546 | 547 | Write-Verbose "Removing the docker files" 548 | $null = Get-ChildItem -Path $script:pathDockerRoot -Recurse | Remove-Item -force -Recurse 549 | 550 | if(Test-Path $script:pathDockerRoot ) {$null = Remove-Item $script:pathDockerRoot -Force} 551 | } 552 | else 553 | { 554 | Write-Warning "Docker is not present under the Program Files. Please check the installation." 555 | } 556 | 557 | Write-Verbose "Removing the path variable" 558 | $null = Remove-PathVar 559 | } 560 | 561 | function InstallContainer 562 | { 563 | if(IsNanoServer) 564 | { 565 | if(HandleProvider) 566 | { 567 | $containerExists = get-package -providername NanoServerPackage -Name *container* -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 568 | 569 | if($containerExists) 570 | { 571 | Write-Verbose "Containers package is already installed. Skipping the install." 572 | return 573 | } 574 | 575 | # Find Container Package 576 | $containerPackage = Find-NanoServerPackage -Name *Container* -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 577 | 578 | if(-not $containerPackage) 579 | { 580 | ThrowError -ExceptionName "System.ArgumentException" ` 581 | -ExceptionMessage "Unable to find the Containers Package from NanoServerPackage Module." ` 582 | -ErrorId "PackageNotFound" ` 583 | -CallerPSCmdlet $PSCmdlet ` 584 | -ErrorCategory InvalidOperation 585 | } 586 | 587 | Write-Verbose "Installing Containers..." 588 | $null = $containerPackage | Install-NanoServerPackage -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 589 | $script:restartRequired = $true 590 | } 591 | else 592 | { 593 | ThrowError -ExceptionName "System.ArgumentException" ` 594 | -ExceptionMessage "Unable to load the NanoServerPackage Module." ` 595 | -ErrorId "ModuleNotFound" ` 596 | -CallerPSCmdlet $PSCmdlet ` 597 | -ErrorCategory InvalidOperation 598 | } 599 | } 600 | else 601 | { 602 | $containerExists = Get-WindowsFeature -Name Containers 603 | 604 | if($containerExists -and $containerExists.Installed) 605 | { 606 | Write-Verbose "Containers feature is already installed. Skipping the install." 607 | return 608 | } 609 | else 610 | { 611 | Write-Verbose "Installing Containers feature..." 612 | Install-WindowsFeature containers 613 | $script:restartRequired = $true 614 | } 615 | } 616 | 617 | Write-Verbose "Installed Containers feature" 618 | } 619 | 620 | function UninstallContainer 621 | { 622 | if(IsNanoServer) 623 | { 624 | return 625 | } 626 | else 627 | { 628 | Uninstall-WindowsFeature containers 629 | } 630 | } 631 | 632 | function HandleProvider 633 | { 634 | # Get the nanoServerpackage provider is present 635 | $getnanoServerPackage = Get-PackageProvider -Name $script:nanoserverPackageProvider -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 636 | 637 | # if not download and install 638 | if(-not $getnanoServerPackage) 639 | { 640 | $repositories = Get-PSRepository -Name PSGallery -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 641 | if(-not $repositories){$null = Register-PSRepository -Default} 642 | 643 | $nanoserverPackage = Find-Module -Name $script:nanoserverPackageProvider -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Repository PSGallery 644 | if(-not $nanoserverPackage) 645 | { 646 | ThrowError -ExceptionName "System.ArgumentException" ` 647 | -ExceptionMessage "Unable to find the Containers Package from NanoServerPackage Module." ` 648 | -ErrorId "PackageNotFound" ` 649 | -CallerPSCmdlet $PSCmdlet ` 650 | -ErrorCategory InvalidOperation 651 | } 652 | 653 | # Install the provider 654 | $null = $nanoserverPackage | Install-Module -Force -SkipPublisherCheck 655 | } 656 | 657 | # Import the provider 658 | $importProvider = Import-PackageProvider -Name $script:nanoserverPackageProvider -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 659 | $importModule = Import-module -Name $script:nanoserverPackageProvider -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -PassThru 660 | 661 | return ($importModule -and $importProvider) 662 | } 663 | 664 | function Update-PathVar 665 | { 666 | $NameOfPath = "Path" 667 | 668 | # Set the environment variable in the Local Process 669 | $envVars = [Environment]::GetEnvironmentVariable($NameOfPath) 670 | $envArr = @() 671 | $envArr = $envVars -split ';' 672 | $envFlag = $true 673 | foreach($envItem in $envArr) 674 | { 675 | if($envItem.Trim() -match [regex]::Escape($script:pathDockerRoot)) 676 | { 677 | $envFlag = $false 678 | break 679 | } 680 | } 681 | if($envFlag) 682 | { 683 | $null = [Environment]::SetEnvironmentVariable($NameOfPath, $envVars + ";" + $script:pathDockerRoot) 684 | } 685 | 686 | # Set the environment variable in the Machine 687 | $currPath = (Microsoft.PowerShell.Management\Get-ItemProperty -Path $script:SystemEnvironmentKey -Name $NameOfPath -ErrorAction SilentlyContinue).Path 688 | $currArr = @() 689 | $currArr = $currPath -split ';' 690 | $currFlag = $true 691 | foreach($currItem in $currArr) 692 | { 693 | if($currItem.Trim() -match [regex]::Escape($script:pathDockerRoot)) 694 | { 695 | $currFlag = $false 696 | break 697 | } 698 | } 699 | if($currFlag) 700 | { 701 | $null = Microsoft.PowerShell.Management\Set-ItemProperty $script:SystemEnvironmentKey -Name $NameOfPath -Value ($currPath + ";" + $script:pathDockerRoot) 702 | 703 | # Nanoserver needs a reboot to persist the registry change 704 | if(IsNanoServer) 705 | { 706 | $script:restartRequired = $true 707 | } 708 | } 709 | } 710 | 711 | function Remove-PathVar 712 | { 713 | $NameOfPath = "Path" 714 | 715 | # Set the environment variable in the Local Process 716 | $envVars = [Environment]::GetEnvironmentVariable($NameOfPath) 717 | $envArr = @() 718 | $envArr = $envVars -split ';' 719 | $envFlag = $false 720 | foreach($envItem in $envArr) 721 | { 722 | if($envItem.Trim() -match [regex]::Escape($script:pathDockerRoot)) 723 | { 724 | $envFlag = $true 725 | break 726 | } 727 | } 728 | if($envFlag) 729 | { 730 | $newPath = $envVars -replace [regex]::Escape($script:pathDockerRoot),$null 731 | $newPath = $newPath -replace (";;"), ";" 732 | $null = [Environment]::SetEnvironmentVariable($NameOfPath, $newPath) 733 | } 734 | 735 | # Set the environment variable in the Machine 736 | $currPath = (Microsoft.PowerShell.Management\Get-ItemProperty -Path $script:SystemEnvironmentKey -Name $NameOfPath -ErrorAction SilentlyContinue).Path 737 | $currArr = @() 738 | $currArr = $currPath -split ';' 739 | $currFlag = $false 740 | foreach($currItem in $currArr) 741 | { 742 | if($currItem.Trim() -match [regex]::Escape($script:pathDockerRoot)) 743 | { 744 | $currFlag = $true 745 | break 746 | } 747 | } 748 | if($currFlag) 749 | { 750 | $newPath = $currPath -replace [regex]::Escape($script:pathDockerRoot),$null 751 | $newPath = $newPath -replace (";;"), ";" 752 | $null = Microsoft.PowerShell.Management\Set-ItemProperty $script:SystemEnvironmentKey -Name $NameOfPath -Value $newPath 753 | } 754 | } 755 | 756 | function Set-ModuleSourcesVariable 757 | { 758 | if(Microsoft.PowerShell.Management\Test-Path $script:file_modules) 759 | { 760 | $script:DockerSources = DeSerialize-PSObject -Path $script:file_modules 761 | } 762 | else 763 | { 764 | $script:DockerSources = [ordered]@{} 765 | $defaultModuleSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ 766 | Name = "DockerDefault" 767 | SourceLocation = $script:dockerURL 768 | Trusted=$false 769 | Registered= $true 770 | InstallationPolicy = "Untrusted" 771 | }) 772 | 773 | $script:DockerSources.Add("DockerDefault", $defaultModuleSource) 774 | Save-ModuleSources 775 | } 776 | } 777 | 778 | function DeSerialize-PSObject 779 | { 780 | [CmdletBinding(PositionalBinding=$false)] 781 | Param 782 | ( 783 | [Parameter(Mandatory=$true)] 784 | $Path 785 | ) 786 | $filecontent = Microsoft.PowerShell.Management\Get-Content -Path $Path 787 | [System.Management.Automation.PSSerializer]::Deserialize($filecontent) 788 | } 789 | 790 | function Save-ModuleSources 791 | { 792 | # check if exists 793 | if(-not (Test-Path $script:location_sources)) 794 | { 795 | $null = mkdir $script:location_sources 796 | } 797 | 798 | # seralize module 799 | Microsoft.PowerShell.Utility\Out-File -FilePath $script:file_modules ` 800 | -Force ` 801 | -InputObject ([System.Management.Automation.PSSerializer]::Serialize($script:DockerSources)) 802 | } 803 | 804 | function Get-SourceList 805 | { 806 | param 807 | ( 808 | [Parameter(Mandatory=$true)] 809 | $sources 810 | ) 811 | 812 | Set-ModuleSourcesVariable 813 | 814 | $listOfSources = @() 815 | 816 | foreach($mySource in $script:DockerSources.Values) 817 | { 818 | if((-not $sources) -or 819 | (($mySource.Name -eq $sources) -or 820 | ($mySource.SourceLocation -eq $sources))) 821 | { 822 | $tempHolder = @{} 823 | 824 | $location = $mySource."SourceLocation" 825 | $tempHolder.Add("SourceLocation", $location) 826 | 827 | $packageSourceName = $mySource.Name 828 | $tempHolder.Add("Name", $packageSourceName) 829 | 830 | $listOfSources += $tempHolder 831 | } 832 | } 833 | 834 | return $listOfSources 835 | } 836 | 837 | function Resolve-ChannelAlias 838 | { 839 | param 840 | ( 841 | [Parameter(Mandatory=$true)] 842 | [psobject] 843 | $Channels, 844 | 845 | [Parameter(Mandatory=$true)] 846 | [String] 847 | $Channel 848 | ) 849 | 850 | while ($Channels.$Channel.PSObject.Properties.Name -contains 'alias') 851 | { 852 | $Channel = $Channels.$Channel.alias 853 | } 854 | 855 | return $Channel 856 | } 857 | 858 | function Find-FromUrl 859 | { 860 | param 861 | ( 862 | [Parameter(Mandatory=$true)] 863 | [ValidateNotNullOrEmpty()] 864 | [Uri] 865 | $Source, 866 | 867 | [Parameter(Mandatory=$true)] 868 | [ValidateNotNullOrEmpty()] 869 | [String] 870 | $SourceName, 871 | 872 | [Parameter(Mandatory=$false)] 873 | [string[]] 874 | $Name, 875 | 876 | [Parameter(Mandatory=$false)] 877 | [String] 878 | $MinimumVersion, 879 | 880 | [Parameter(Mandatory=$false)] 881 | [String] 882 | $MaximumVersion, 883 | 884 | [Parameter(Mandatory=$false)] 885 | [String] 886 | $RequiredVersion, 887 | 888 | [Parameter(Mandatory=$false)] 889 | [switch] 890 | $AllVersions 891 | ) 892 | 893 | if ([string]::IsNullOrWhiteSpace($Name)) 894 | { 895 | $Name = "*" 896 | } 897 | 898 | if ([System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Name)) 899 | { 900 | if('docker' -notlike $Name) {return $null} 901 | } 902 | elseif('docker' -ne $Name) {return $Null} 903 | 904 | $searchFile = Get-SearchIndex -fwdLink $Location ` 905 | -SourceName $SourceName 906 | 907 | [String] $searchFileContent = Get-Content -Path $searchFile 908 | 909 | if(-not $searchFileContent) 910 | { 911 | return $null 912 | } 913 | 914 | $updatedContent = $searchFileContent.Trim(" .-`t`n`r") 915 | $contents = $updatedContent | ConvertFrom-Json 916 | $channels = $contents.channels 917 | $versions = $contents.versions 918 | $channelValues = $channels | Get-Member -MemberType NoteProperty 919 | $searchResults = @() 920 | 921 | # If name is null or whitespace, interpret as * 922 | if ([string]::IsNullOrWhiteSpace($Name)) 923 | { 924 | $Name = "*" 925 | } 926 | 927 | # Set the default channel, allowing $RequiredVersion to override when set to a channel name. 928 | $defaultChannel = 'cs' 929 | if ($RequiredVersion) 930 | { 931 | foreach ($channel in $channelValues) 932 | { 933 | if ($RequiredVersion -eq $channel.Name) 934 | { 935 | $defaultChannel = $channel.Name 936 | $RequiredVersion = $null 937 | break 938 | } 939 | } 940 | } 941 | 942 | # if no versions are mentioned, just provide the default version, i.e.: CS 943 | if((-not ($MinimumVersion -or $MaximumVersion -or $RequiredVersion -or $AllVersions))) 944 | { 945 | $resolvedChannel = Resolve-ChannelAlias -Channels $channels -Channel $defaultChannel 946 | $RequiredVersion = $channels.$resolvedChannel.version 947 | } 948 | 949 | # if a particular version is requested, provide that version only 950 | if($RequiredVersion) 951 | { 952 | if($versions.PSObject.properties.name -contains $RequiredVersion) 953 | { 954 | $obj = Get-ResultObject -JSON $versions -Version $RequiredVersion 955 | $searchResults += $obj 956 | return $searchResults 957 | } 958 | else { 959 | return $null 960 | } 961 | } 962 | 963 | $savedVersion = New-Object $script:SemVerTypeName -ArgumentList '0.0.0' 964 | 965 | # version requirement 966 | # compare different versions 967 | foreach($channel in $channelValues) 968 | { 969 | if ($channel.Name -eq $defaultChannel) 970 | { 971 | continue 972 | } 973 | else 974 | { 975 | $dockerName = "Docker" 976 | $versionName = Resolve-ChannelAlias -Channels $channels -Channel $channel.Name 977 | $versionValue = $channels.$versionName.version 978 | 979 | $toggle = $false 980 | 981 | # Check if the search string has * in it 982 | if ([System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Name)) 983 | { 984 | if($dockerName -like $Name) 985 | { 986 | $toggle = $true 987 | } 988 | else 989 | { 990 | continue 991 | } 992 | } 993 | else 994 | { 995 | if($dockerName -eq $Name) 996 | { 997 | $toggle = $true 998 | } 999 | else 1000 | { 1001 | continue 1002 | } 1003 | } 1004 | 1005 | $thisVersion = New-Object $script:SemVerTypeName -ArgumentList $versionValue 1006 | 1007 | if($MinimumVersion) 1008 | { 1009 | $convertedMinimumVersion = New-Object $script:SemVerTypeName -ArgumentList $MinimumVersion 1010 | if($thisVersion -ge $convertedMinimumVersion) 1011 | { 1012 | $toggle = $true 1013 | } 1014 | else 1015 | { 1016 | $toggle = $false 1017 | continue 1018 | } 1019 | } 1020 | 1021 | if($MaximumVersion) 1022 | { 1023 | $convertedMaximumVersion = New-Object $script:SemVerTypeName -ArgumentList $MaximumVersion 1024 | if($thisVersion -le $convertedMaximumVersion) 1025 | { 1026 | $toggle = $true 1027 | } 1028 | else 1029 | { 1030 | $toggle = $false 1031 | continue 1032 | } 1033 | } 1034 | 1035 | if($toggle) 1036 | { 1037 | if($thisVersion -ge $savedVersion) {$savedVersion = $thisVersion} 1038 | } 1039 | 1040 | if($AllVersions) 1041 | { 1042 | if($toggle) 1043 | { 1044 | $obj = Get-ResultObject -JSON $versions -Version $versionValue 1045 | $searchResults += $obj 1046 | } 1047 | } 1048 | } 1049 | } 1050 | 1051 | if(-not $AllVersions) 1052 | { 1053 | if($savedVersion -eq '0.0.0'){return $null} 1054 | 1055 | $ver = $savedVersion.ToString() 1056 | $obj = Get-ResultObject -JSON $versions -Version $ver 1057 | $searchResults += $obj 1058 | } 1059 | 1060 | return $searchResults 1061 | } 1062 | 1063 | function Get-ResultObject 1064 | { 1065 | param 1066 | ( 1067 | [Parameter(Mandatory=$true)] 1068 | [string] 1069 | $Version, 1070 | 1071 | [Parameter(Mandatory=$true)] 1072 | [psobject] 1073 | $JSON 1074 | ) 1075 | 1076 | if($JSON.$Version) 1077 | { 1078 | $description = "" 1079 | if($versions.$Version.Psobject.properties.name -contains "notes") 1080 | { 1081 | $URL = $versions.$Version.'notes' 1082 | if($URL.StartsWith("https://")) 1083 | { 1084 | try 1085 | { 1086 | $description = (Invoke-WebRequest -Uri $URL).Content 1087 | } 1088 | catch 1089 | { 1090 | Write-verbose "Bad URL provided for description: $URL" 1091 | } 1092 | } 1093 | else 1094 | { 1095 | $description = $versions.$Version.'notes' 1096 | } 1097 | } 1098 | 1099 | $obj = $versions.$Version.PSObject.Copy() 1100 | $null = $obj | Add-Member NoteProperty Version $Version 1101 | $null = $obj | Add-Member NoteProperty Name "Docker" 1102 | $null = $obj | Add-Member NoteProperty SourceName $SourceName 1103 | $null = $obj | Add-Member NoteProperty Description $description 1104 | 1105 | return $obj 1106 | } 1107 | 1108 | return $null 1109 | } 1110 | 1111 | function Get-SearchIndex 1112 | { 1113 | param 1114 | ( 1115 | [Parameter(Mandatory=$true)] 1116 | [string] 1117 | $fwdLink, 1118 | 1119 | [Parameter(Mandatory=$true)] 1120 | [string] 1121 | $SourceName 1122 | ) 1123 | 1124 | $fullUrl = Resolve-FwdLink $fwdLink 1125 | $searchIndex = $SourceName + "_" + $script:DockerSearchIndex 1126 | $destination = Join-Path $script:location_modules $searchIndex 1127 | 1128 | if(-not(Test-Path $script:location_modules)) 1129 | { 1130 | $null = mkdir $script:location_modules 1131 | } 1132 | 1133 | if(Test-Path $destination) 1134 | { 1135 | $null = Remove-Item $destination 1136 | $null = DownloadFile -downloadURL $fullUrl ` 1137 | -destination $destination 1138 | } 1139 | else 1140 | { 1141 | $null = DownloadFile -downloadURL $fullUrl ` 1142 | -destination $destination 1143 | } 1144 | 1145 | return $destination 1146 | } 1147 | 1148 | function Resolve-FwdLink 1149 | { 1150 | param 1151 | ( 1152 | [parameter(Mandatory=$false)] 1153 | [System.String]$Uri 1154 | ) 1155 | 1156 | $response = Get-HttpResponse -Uri $Uri 1157 | 1158 | if(-not $response) 1159 | { 1160 | # This is not a forward link. Return the original URI 1161 | return $Uri 1162 | } 1163 | 1164 | $link = $response.Result.RequestMessage.RequestUri 1165 | $fullUrl = $link.AbsoluteUri 1166 | return $fullUrl 1167 | } 1168 | 1169 | function Get-HttpResponse 1170 | { 1171 | param 1172 | ( 1173 | [Parameter(Mandatory=$false)] 1174 | [System.String] 1175 | $Uri 1176 | ) 1177 | 1178 | if(-not (IsNanoServer)) 1179 | { 1180 | Add-Type -AssemblyName System.Net.Http 1181 | } 1182 | 1183 | $httpClient = New-Object System.Net.Http.HttpClient 1184 | $request = New-Object System.Net.Http.HttpRequestMessage 1185 | $request.Method = [System.Net.Http.HttpMethod]::Head 1186 | $request.RequestUri = $Uri 1187 | $response = $httpclient.SendAsync($request) 1188 | 1189 | return $response 1190 | } 1191 | 1192 | function New-SoftwareIdentityFromDockerInfo 1193 | { 1194 | param 1195 | ( 1196 | [Parameter(Mandatory=$true)] 1197 | [PSCustomObject] 1198 | $DockerInfo 1199 | ) 1200 | 1201 | $fastPackageReference = $DockerInfo.SourceName + 1202 | $separator + $DockerInfo.Name + 1203 | $separator + $DockerInfo.Version + 1204 | $separator + $DockerInfo.Description + 1205 | $separator + $dockerInfo.date + 1206 | $separator + $dockerInfo.url + 1207 | $separator + $dockerInfo.size + 1208 | $separator + $dockerInfo.sha256 1209 | 1210 | $params = @{ 1211 | FastPackageReference = $fastPackageReference; 1212 | Name = $DockerInfo.Name; 1213 | Version = $DockerInfo.Version; 1214 | Source = $DockerInfo.SourceName; 1215 | versionScheme = "MultiPartNumeric"; 1216 | Summary = $DockerInfo.Description; 1217 | } 1218 | 1219 | New-SoftwareIdentity @params 1220 | } 1221 | 1222 | function Set-ModuleSourcesVariable 1223 | { 1224 | [CmdletBinding()] 1225 | param([switch]$Force) 1226 | 1227 | if(Microsoft.PowerShell.Management\Test-Path $script:file_modules) 1228 | { 1229 | $script:DockerSources = DeSerialize-PSObject -Path $script:file_modules 1230 | } 1231 | else 1232 | { 1233 | $script:DockerSources = [ordered]@{} 1234 | 1235 | $defaultModuleSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ 1236 | Name = "DockerDefault" 1237 | SourceLocation = $script:dockerURL 1238 | Trusted=$false 1239 | Registered= $true 1240 | InstallationPolicy = "Untrusted" 1241 | }) 1242 | 1243 | $script:DockerSources.Add("DockerDefault", $defaultModuleSource) 1244 | Save-ModuleSources 1245 | } 1246 | } 1247 | 1248 | function Get-DynamicOptions 1249 | { 1250 | param 1251 | ( 1252 | [Microsoft.PackageManagement.MetaProvider.PowerShell.OptionCategory] 1253 | $category 1254 | ) 1255 | 1256 | switch($category) 1257 | { 1258 | Install 1259 | { 1260 | Write-Output -InputObject (New-DynamicOption -Category $category -Name "Update" -ExpectedType Switch -IsRequired $false) 1261 | } 1262 | } 1263 | } 1264 | 1265 | function Add-PackageSource 1266 | { 1267 | [CmdletBinding()] 1268 | param 1269 | ( 1270 | [string] 1271 | $Name, 1272 | 1273 | [string] 1274 | $Location, 1275 | 1276 | [bool] 1277 | $Trusted 1278 | ) 1279 | 1280 | Set-ModuleSourcesVariable 1281 | 1282 | $Options = $request.Options 1283 | 1284 | # Add new module source 1285 | $moduleSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ 1286 | Name = $Name 1287 | SourceLocation = $Location 1288 | Trusted=$Trusted 1289 | Registered= $true 1290 | InstallationPolicy = if($Trusted) {'Trusted'} else {'Untrusted'} 1291 | }) 1292 | 1293 | #TODO: Check if name already exists 1294 | $script:DockerSources.Add($Name, $moduleSource) 1295 | 1296 | Save-ModuleSources 1297 | 1298 | Write-Output -InputObject (New-PackageSourceFromModuleSource -ModuleSource $moduleSource) 1299 | } 1300 | 1301 | function Remove-PackageSource 1302 | { 1303 | param 1304 | ( 1305 | [string] 1306 | $Name 1307 | ) 1308 | 1309 | Set-ModuleSourcesVariable -Force 1310 | 1311 | if(-not $script:DockerSources.Contains($Name)) 1312 | { 1313 | Write-Error -Message "Package source $Name not found" ` 1314 | -ErrorId "Package source $Name not found" ` 1315 | -Category InvalidOperation ` 1316 | -TargetObject $Name 1317 | continue 1318 | } 1319 | 1320 | $script:DockerSources.Remove($Name) 1321 | 1322 | Save-ModuleSources 1323 | } 1324 | 1325 | function Resolve-PackageSource 1326 | { 1327 | Set-ModuleSourcesVariable 1328 | $SourceName = $request.PackageSources 1329 | if(-not $SourceName) 1330 | { 1331 | $SourceName = "*" 1332 | } 1333 | 1334 | foreach($moduleSourceName in $SourceName) 1335 | { 1336 | if($request.IsCanceled) 1337 | { 1338 | return 1339 | } 1340 | 1341 | $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $moduleSourceName,$script:wildcardOptions 1342 | $moduleSourceFound = $false 1343 | 1344 | $script:DockerSources.GetEnumerator() | 1345 | Microsoft.PowerShell.Core\Where-Object {$wildcardPattern.IsMatch($_.Key)} | 1346 | Microsoft.PowerShell.Core\ForEach-Object { 1347 | $moduleSource = $script:DockerSources[$_.Key] 1348 | $packageSource = New-PackageSourceFromModuleSource -ModuleSource $moduleSource 1349 | Write-Output -InputObject $packageSource 1350 | $moduleSourceFound = $true 1351 | } 1352 | 1353 | if(-not $moduleSourceFound) 1354 | { 1355 | $sourceName = Get-SourceName -Location $moduleSourceName 1356 | 1357 | if($sourceName) 1358 | { 1359 | $moduleSource = $script:DockerSources[$sourceName] 1360 | $packageSource = New-PackageSourceFromModuleSource -ModuleSource $moduleSource 1361 | Write-Output -InputObject $packageSource 1362 | } 1363 | } 1364 | } 1365 | } 1366 | 1367 | function New-PackageSourceFromModuleSource 1368 | { 1369 | param 1370 | ( 1371 | [Parameter(Mandatory=$true)] 1372 | $ModuleSource 1373 | ) 1374 | 1375 | $packageSourceDetails = @{} 1376 | 1377 | # create a new package source 1378 | $src = New-PackageSource -Name $ModuleSource.Name ` 1379 | -Location $ModuleSource.SourceLocation ` 1380 | -Trusted $ModuleSource.Trusted ` 1381 | -Registered $ModuleSource.Registered ` 1382 | -Details $packageSourceDetails 1383 | 1384 | # return the package source object. 1385 | Write-Output -InputObject $src 1386 | } 1387 | 1388 | function Get-SourceName 1389 | { 1390 | [CmdletBinding()] 1391 | [OutputType("string")] 1392 | Param 1393 | ( 1394 | [Parameter(Mandatory=$true)] 1395 | [ValidateNotNullOrEmpty()] 1396 | [string] 1397 | $Location 1398 | ) 1399 | 1400 | Set-ModuleSourcesVariable 1401 | 1402 | foreach($psModuleSource in $script:DockerSources.Values) 1403 | { 1404 | if(($psModuleSource.Name -eq $Location) -or 1405 | ($psModuleSource.SourceLocation -eq $Location)) 1406 | { 1407 | return $psModuleSource.Name 1408 | } 1409 | } 1410 | } 1411 | 1412 | function DownloadPackageHelper 1413 | { 1414 | [CmdletBinding()] 1415 | param 1416 | ( 1417 | [Parameter(Mandatory=$true)] 1418 | [ValidateNotNullOrEmpty()] 1419 | [string] 1420 | $FastPackageReference, 1421 | 1422 | [Parameter()] 1423 | [ValidateNotNullOrEmpty()] 1424 | [string] 1425 | $Location, 1426 | 1427 | [Parameter(Mandatory=$true)] 1428 | [ValidateNotNullOrEmpty()] 1429 | $request 1430 | ) 1431 | 1432 | [string[]] $splitterArray = @("$separator") 1433 | [string[]] $resultArray = $fastPackageReference.Split($splitterArray, [System.StringSplitOptions]::None) 1434 | 1435 | if((-not $resultArray) -or ($resultArray.count -ne 8)){Write-Debug "Fast package reference doesn't have required parts."} 1436 | 1437 | $source = $resultArray[0] 1438 | $name = $resultArray[1] 1439 | $version = $resultArray[2] 1440 | $description = $resultArray[3] 1441 | $originPath = $resultArray[5] 1442 | $size = $resultArray[6] 1443 | $sha = $resultArray[7] 1444 | $date = $resultArray[4] 1445 | 1446 | $options = $request.Options 1447 | 1448 | foreach( $o in $options.Keys ) 1449 | { 1450 | Write-Debug ( "OPTION: {0} => {1}" -f ($o, $options[$o]) ) 1451 | } 1452 | 1453 | $Force = $false 1454 | if($options.ContainsKey("Force")) 1455 | { 1456 | $Force = $options['Force'] 1457 | } 1458 | 1459 | if(-not (Test-Path $Location)) 1460 | { 1461 | if($Force) 1462 | { 1463 | Write-Verbose "Creating: $Location as it doesn't exist." 1464 | mkdir $Location 1465 | } 1466 | else 1467 | { 1468 | $errorMessage = ("Cannot find the path '{0}' because it does not exist" -f $Location) 1469 | ThrowError -ExceptionName "System.ArgumentException" ` 1470 | -ExceptionMessage $errorMessage ` 1471 | -ErrorId "PathNotFound" ` 1472 | -CallerPSCmdlet $PSCmdlet ` 1473 | -ExceptionObject $Location ` 1474 | -ErrorCategory InvalidArgument 1475 | } 1476 | } 1477 | 1478 | $fullDestinationPath = GenerateFullPath -Location $Location ` 1479 | -Name $name ` 1480 | -Version $Version 1481 | 1482 | if(Test-Path $fullDestinationPath) 1483 | { 1484 | if($Force) 1485 | { 1486 | $existingFileItem = get-item $fullDestinationPath 1487 | if($existingFileItem.isreadonly) 1488 | { 1489 | throw "Cannot remove read-only file $fullDestinationPath. Remove read-only and use -Force again." 1490 | } 1491 | else 1492 | { 1493 | Write-Verbose "$fullDestinationPath already exists. Deleting and downloading again." 1494 | Remove-Item $fullDestinationPath -Force 1495 | DownloadFile -downloadUrl $originPath -destination $fullDestinationPath 1496 | } 1497 | } 1498 | else 1499 | { 1500 | Write-Verbose "$fullDestinationPath already exists. Skipping save. Use -Force to overwrite." 1501 | } 1502 | } 1503 | else 1504 | { 1505 | DownloadFile -downloadUrl $originPath -destination $fullDestinationPath 1506 | } 1507 | 1508 | $hashCheck = VerifyHashCheck -destination $fullDestinationPath -hash $sha 1509 | 1510 | if((-not $hashCheck)) 1511 | { 1512 | $null = remove-item -Path $fullDestinationPath -Force 1513 | Write-Error -Message "Cannot verify the file SHA256. Deleting the file." 1514 | } 1515 | 1516 | Write-Verbose "Hash verified!" 1517 | 1518 | $savedWindowsPackageItem = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ 1519 | SourceName = $source 1520 | Name = $name 1521 | Version = $version 1522 | Description = $description 1523 | Date = $date 1524 | URL = $originPath 1525 | Size = $size 1526 | sha256 = $sha 1527 | }) 1528 | 1529 | Write-Output (New-SoftwareIdentityFromDockerInfo $savedWindowsPackageItem) 1530 | } 1531 | 1532 | function GenerateFullPath 1533 | { 1534 | param 1535 | ( 1536 | [Parameter(Mandatory=$true)] 1537 | [System.String] 1538 | $Location, 1539 | 1540 | [Parameter(Mandatory=$true)] 1541 | [System.String] 1542 | $Name, 1543 | 1544 | [Parameter(Mandatory=$true)] 1545 | [System.String] 1546 | $Version 1547 | ) 1548 | 1549 | $fileExtension = "." + $script:Installer_Extension 1550 | $Name = $Name.TrimEnd($fileExtension) 1551 | $fileName = $Name + "-" + $Version.ToString().replace('.','-') + $fileExtension 1552 | $fullPath = Join-Path $Location $fileName 1553 | return $fullPath 1554 | } 1555 | 1556 | function DownloadFile 1557 | { 1558 | [CmdletBinding()] 1559 | param 1560 | ( 1561 | [Parameter(Mandatory=$true)] 1562 | [System.String] 1563 | $downloadURL, 1564 | 1565 | [Parameter(Mandatory=$true)] 1566 | [System.String] 1567 | $destination 1568 | ) 1569 | 1570 | try 1571 | { 1572 | if(-not (CheckDiskSpace -Destination $destination -URL $downloadURL)) 1573 | { 1574 | return 1575 | } 1576 | 1577 | # Download the file 1578 | if($downloadURL.StartsWith("https://")) 1579 | { 1580 | Write-Verbose "Downloading $downloadUrl to $destination" 1581 | $startTime = Get-Date 1582 | Write-Verbose "About to download" 1583 | Invoke-WebRequest -Uri $downloadURL ` 1584 | -OutFile $destination 1585 | 1586 | Write-Verbose "Finished downloading" 1587 | $endTime = Get-Date 1588 | $difference = New-TimeSpan -Start $startTime -End $endTime 1589 | $downloadTime = "Downloaded in " + $difference.Hours + " hours, " + $difference.Minutes + " minutes, " + $difference.Seconds + " seconds." 1590 | Write-Verbose $downloadTime 1591 | } 1592 | } 1593 | catch 1594 | { 1595 | ThrowError -CallerPSCmdlet $PSCmdlet ` 1596 | -ExceptionName $_.Exception.GetType().FullName ` 1597 | -ExceptionMessage $_.Exception.Message ` 1598 | -ExceptionObject $downloadURL ` 1599 | -ErrorId FailedToDownload ` 1600 | -ErrorCategory InvalidOperation 1601 | } 1602 | } 1603 | 1604 | function ThrowError 1605 | { 1606 | param 1607 | ( 1608 | [parameter(Mandatory = $true)] 1609 | [ValidateNotNullOrEmpty()] 1610 | [System.Management.Automation.PSCmdlet] 1611 | $CallerPSCmdlet, 1612 | 1613 | [parameter(Mandatory = $true)] 1614 | [ValidateNotNullOrEmpty()] 1615 | [System.String] 1616 | $ExceptionName, 1617 | 1618 | [parameter(Mandatory = $true)] 1619 | [ValidateNotNullOrEmpty()] 1620 | [System.String] 1621 | $ExceptionMessage, 1622 | 1623 | [System.Object] 1624 | $ExceptionObject, 1625 | 1626 | [parameter(Mandatory = $true)] 1627 | [ValidateNotNullOrEmpty()] 1628 | [System.String] 1629 | $ErrorId, 1630 | 1631 | [parameter(Mandatory = $true)] 1632 | [ValidateNotNull()] 1633 | [System.Management.Automation.ErrorCategory] 1634 | $ErrorCategory 1635 | ) 1636 | 1637 | $exception = New-Object $ExceptionName $ExceptionMessage; 1638 | $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $ErrorId, $ErrorCategory, $ExceptionObject 1639 | $CallerPSCmdlet.ThrowTerminatingError($errorRecord) 1640 | } 1641 | 1642 | function CheckDiskSpace 1643 | { 1644 | param 1645 | ( 1646 | [parameter(Mandatory = $true)] 1647 | [ValidateNotNullOrEmpty()] 1648 | [System.String] 1649 | $Destination, 1650 | 1651 | [parameter(Mandatory = $true)] 1652 | [ValidateNotNullOrEmpty()] 1653 | [System.String] 1654 | $URL 1655 | ) 1656 | 1657 | $size = 0 1658 | 1659 | if($URL.StartsWith("https://")) 1660 | { 1661 | $response = Get-HttpResponse -Uri $URL 1662 | $size = $response.Result.Content.Headers.ContentLength 1663 | } 1664 | 1665 | $parent = Split-Path $Destination -Parent 1666 | $Drive = (Get-Item $parent).PSDrive.Name 1667 | $getDriveSpace = get-ciminstance win32_logicaldisk | Where-Object {$_.DeviceID -match $Drive} | % Freespace 1668 | 1669 | $contentLengthInMB = [math]::Round($size/1mb, 2) 1670 | $driveSpaceInIMB = [math]::Round($getDriveSpace/1mb, 2) 1671 | 1672 | Write-Verbose "Download size: $($contentLengthInMB)MB" 1673 | Write-Verbose "Free space on the drive: $($driveSpaceInIMB)MB" 1674 | 1675 | if($size -ge ($getDriveSpace * 0.95)) 1676 | { 1677 | Write-Error "Not enough space to save the file" 1678 | return $false 1679 | } 1680 | 1681 | return $true 1682 | } 1683 | 1684 | function VerifyHashCheck 1685 | { 1686 | param 1687 | ( 1688 | [parameter(Mandatory = $true)] 1689 | [ValidateNotNullOrEmpty()] 1690 | [System.String] 1691 | $Destination, 1692 | 1693 | [parameter(Mandatory = $true)] 1694 | [ValidateNotNullOrEmpty()] 1695 | [System.String] 1696 | $hash 1697 | ) 1698 | 1699 | Write-Verbose "Verifying Hash of the downloaded file." 1700 | 1701 | $fileHash = Get-FileHash -Path $Destination ` 1702 | -Algorithm SHA256 1703 | 1704 | if($fileHash.Psobject.properties.name -Contains "Hash") 1705 | { 1706 | $fileSha256 = $fileHash.Hash 1707 | } 1708 | else 1709 | { 1710 | Write-Verbose "Hash for the original file not available." 1711 | return $false 1712 | } 1713 | 1714 | return ($hash -ieq $fileSha256) 1715 | } 1716 | 1717 | function Test-AdminPrivilege 1718 | { 1719 | [CmdletBinding()] 1720 | [OutputType([bool])] 1721 | Param() 1722 | 1723 | $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent() 1724 | $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID) 1725 | 1726 | # Get the security principal for the Administrator role 1727 | $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator 1728 | 1729 | # Check to see if we are currently running "as Administrator" 1730 | return ($myWindowsPrincipal.IsInRole($adminRole)) 1731 | } 1732 | 1733 | function IsNanoServer 1734 | { 1735 | if ($script:isNanoServerInitialized) 1736 | { 1737 | return $script:isNanoServer 1738 | } 1739 | else 1740 | { 1741 | $operatingSystem = Get-CimInstance -ClassName win32_operatingsystem 1742 | $systemSKU = $operatingSystem.OperatingSystemSKU 1743 | $script:isNanoServer = ($systemSKU -eq 109) -or ($systemSKU -eq 144) -or ($systemSKU -eq 143) 1744 | $script:isNanoServerInitialized = $true 1745 | return $script:isNanoServer 1746 | } 1747 | } 1748 | 1749 | function IsClient 1750 | { 1751 | 1752 | } 1753 | 1754 | function Install-NuGetClientBinary 1755 | { 1756 | [CmdletBinding(SupportsShouldProcess = $true)] 1757 | param 1758 | ( 1759 | [parameter(Mandatory = $true)] 1760 | [ValidateNotNullOrEmpty()] 1761 | [System.Management.Automation.PSCmdlet] 1762 | $CallerPSCmdlet, 1763 | 1764 | [parameter()] 1765 | [switch] 1766 | $Force 1767 | ) 1768 | 1769 | if($script:NuGetProvider) 1770 | { 1771 | return 1772 | } 1773 | 1774 | $InstallNuGetProviderShouldContinueQuery = "DockerMsftProvider requires NuGet provider. The NuGet provider must be available in '{0}' or '{1}'. You can also install the NuGet provider by running 'Install-PackageProvider -Name NuGet -Force'. Do you want DockerMsftProvider to install and import the NuGet provider now?" 1775 | $InstallNuGetProviderShouldContinueCaption = "NuGet provider is required to continue" 1776 | $CouldNotInstallNuGetProvider = "NuGet provider is required. Please ensure that NuGet provider is installed." 1777 | $DownloadingNugetProvider = "Installing NuGet provider." 1778 | 1779 | $bootstrapNuGetProvider = (-not $script:NuGetProvider) 1780 | 1781 | if($bootstrapNuGetProvider) 1782 | { 1783 | # Bootstrap the NuGet provider only if it is not available. 1784 | # By default PackageManagement loads the latest version of the NuGet provider. 1785 | $nugetProvider = PackageManagement\Get-PackageProvider -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | 1786 | Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $script:NuGetProviderName} 1787 | if($nugetProvider) 1788 | { 1789 | $script:NuGetProvider = $nugetProvider 1790 | $bootstrapNuGetProvider = $false 1791 | 1792 | return 1793 | } 1794 | else 1795 | { 1796 | $nugetProvider = PackageManagement\Get-PackageProvider -ListAvailable -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | 1797 | Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $script:NuGetProviderName} 1798 | 1799 | if($nugetProvider) 1800 | { 1801 | $null = PackageManagement\Import-PackageProvider -Name $script:NuGetProviderName -Force 1802 | $nugetProvider = PackageManagement\Get-PackageProvider -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | 1803 | Microsoft.PowerShell.Core\Where-Object {$_.Name -eq $script:NuGetProviderName} 1804 | if($nugetProvider) 1805 | { 1806 | $script:NuGetProvider = $nugetProvider 1807 | $bootstrapNuGetProvider = $false 1808 | 1809 | return 1810 | } 1811 | } 1812 | } 1813 | } 1814 | 1815 | # We should prompt only once for bootstrapping the NuGet provider 1816 | 1817 | # Should continue message for bootstrapping only NuGet provider 1818 | $shouldContinueQueryMessage = $InstallNuGetProviderShouldContinueQuery -f @($script:NuGetBinaryProgramDataPath,$script:NuGetBinaryLocalAppDataPath) 1819 | $shouldContinueCaption = $InstallNuGetProviderShouldContinueCaption 1820 | 1821 | if($Force -or $request.ShouldContinue($shouldContinueQueryMessage, $shouldContinueCaption)) 1822 | { 1823 | if($bootstrapNuGetProvider) 1824 | { 1825 | Write-Verbose -Message $DownloadingNugetProvider 1826 | 1827 | $scope = 'CurrentUser' 1828 | if(Test-AdminPrivilege) 1829 | { 1830 | $scope = 'AllUsers' 1831 | } 1832 | 1833 | # Bootstrap the NuGet provider 1834 | $null = PackageManagement\Install-PackageProvider -Name $script:NuGetProviderName ` 1835 | -Scope $scope ` 1836 | -Force 1837 | 1838 | # Force import ensures that nuget provider with minimum version got loaded. 1839 | $null = PackageManagement\Import-PackageProvider -Name $script:NuGetProviderName ` 1840 | -Force 1841 | 1842 | $nugetProvider = PackageManagement\Get-PackageProvider -Name $script:NuGetProviderName 1843 | 1844 | if ($nugetProvider) 1845 | { 1846 | $script:NuGetProvider = $nugetProvider 1847 | } 1848 | } 1849 | } 1850 | 1851 | $message = $null 1852 | $errorId = $null 1853 | $failedToBootstrapNuGetProvider = $false 1854 | 1855 | if($bootstrapNuGetProvider -and -not $script:NuGetProvider) 1856 | { 1857 | $failedToBootstrapNuGetProvider = $true 1858 | 1859 | $message = $CouldNotInstallNuGetProvider 1860 | $errorId = 'CouldNotInstallNuGetProvider' 1861 | } 1862 | 1863 | # Throw the error message if one of the above conditions are met 1864 | if($message -and $errorId) 1865 | { 1866 | ThrowError -ExceptionName "System.InvalidOperationException" ` 1867 | -ExceptionMessage $message ` 1868 | -ErrorId $errorId ` 1869 | -CallerPSCmdlet $CallerPSCmdlet ` 1870 | -ErrorCategory InvalidOperation 1871 | } 1872 | } 1873 | 1874 | #endregion 1875 | -------------------------------------------------------------------------------- /Json.coreclr.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OneGet/MicrosoftDockerProvider/470b97f7759395fa0b7dcf9e6edca0ca07859183/Json.coreclr.dll -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DockerMsftProvider 2 | 3 | Copyright (c) Microsoft Corporation 4 | 5 | All rights reserved. 6 | 7 | The MIT License (MIT) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## IMPORTANT - THIS PROVIDER IS NOW DEPRECATED 2 | As of May 23rd 2023 the backing service for this provider has been shutdown. You can find alternative options at Windows Container Documentation - Setup Environment. 3 | 4 | For more information on the deprecation please see the following blog posts: 5 | [Updates to the Windows Container Runtime support](https://techcommunity.microsoft.com/t5/containers/updates-to-the-windows-container-runtime-support/ba-p/2788799) 6 | [Reminder - Updates to Windows Container Runtime Support](https://techcommunity.microsoft.com/t5/containers/reminder-updates-to-windows-container-runtime-support/ba-p/3620989) 7 | 8 | In the near future this repo will be marked archived. 9 | 10 | #### Preserving the original readme contents: 11 | 12 | --- 13 | 14 | 15 | ### Introduction 16 | #### Install a Docker image from the online Package repository 17 | 18 | The Docker installer for Windows is now available in an online package repository. They can be found and installed using the Docker provider of PackageManagement (a.k.a. OneGet) PowerShell module. **The provider needs to be installed before using it.** The following PowerShell cmdlets can be used to install the provider. 19 | 20 | ##### Step 1: Install the OneGet docker provider 21 | 22 | 1. `Import-Module -Name DockerMsftProvider -Force` 23 | 2. `Import-Packageprovider -Name DockerMsftProvider -Force` 24 | 25 | ##### Step 2: Install Docker 26 | *New installation:* 27 | `Install-Package -Name docker -ProviderName DockerMsftProvider -Verbose` 28 | 29 | *Upgrade to the latest version of docker:* 30 | `Install-Package -Name docker -ProviderName DockerMsftProvider -Verbose -Update` 31 | 32 | Once the provider is installed and imported, you can search, download, or install Docker using OneGet PowerShell cmdlets: 33 | * Find-Package 34 | * Save-Package 35 | * Install-Package 36 | * Uninstall-Package 37 | * Get-Package 38 | 39 | #### Register a source 40 | 41 | ##### Register an URL to be used with DockerMsftProvider 42 | Register-PackageSource -ProviderName DockerMsftProvider -Name AlternateSource -Location https://contoso.com/metaData.json 43 | 44 | ##### Enlist all the registered sources 45 | Get-PackageSource -ProviderName DockerMsftProvider 46 | 47 | #### Search a Docker installer 48 | 49 | ##### Example 1: Find the latest version of all available Docker installers. 50 | Find-Package -providerName DockerMsftProvider 51 | 52 | ##### Example 2: Search by version, according to -RequiredVersion, -MinimumVersion, and -MaximumVersion requirements. With -AllVersions parameter, all available versions of Docker installers are returned. Without it, only the latest version is returned. 53 | Find-Package -providerName DockerMsftProvider -AllVersions 54 | 55 | #### Install docker 56 | 57 | ##### Example 1: Install the latest version of docker to the local machine. 58 | Install-Package -Name docker -ProviderName DockerMsftProvider -Verbose 59 | 60 | ##### Example 2: Install docker with pipeline result from the search cmdlets. 61 | Find-Package -ProviderName DockerMsftProvider | Install-Package -Verbose 62 | 63 | #### Download Docker 64 | You can download and save Docker installer without installation, using Save-Package. This cmdlet accepts pipeline result from the search cmdlets. If you have multiple sources, please provide the source for download. 65 | 66 | ##### Example 1: Download and save Docker installer to a directory that matches the wildcard path. The latest version will be saved if you do not specify the version requirements. 67 | Save-Package -ProviderName DockerMsftProvider -Name Docker -Path .\temp -MinimumVersion 1.2.3 68 | 69 | ##### Example 2: Download and save Docker installer from the search cmdlets. 70 | Find-package -ProviderName DockerMsftProvider | Save-Package -Path . 71 | 72 | #### Get docker 73 | 74 | 75 | ##### Example 1: Inventory docker installation on the local machine. 76 | Get-Package -ProviderName DockerMsftProvider 77 | 78 | #### Uninstall docker 79 | Uninstalls Docker from the local machine. 80 | 81 | ##### Example 1: Uninstall docker from the local machine. 82 | Uninstall-Package -ProviderName DockerMsftProvider -Name dOcKeR -Verbose 83 | 84 | #### Update docker 85 | Updates current installation of docker with the requested version 86 | 87 | ##### Example 1: Update docker 88 | Install-Package -Name docker -ProviderName DockerMsftProvider -Verbose -Update 89 | 90 | ### Manual Steps 91 | Once docker is installed, you will need to restart the machine 92 | After the machine is restarted, docker service needs to be in the running state 93 | 94 | After you have installed the required KB (KB3176936 or higher) you will need to restart the machine 95 | 96 | ### Version 97 | 1.0.0.8 98 | 99 | ### Version History 100 | 101 | #### 0.1.0.0 102 | Initial release 103 | 104 | #### 0.1.0.1 105 | Bug fixes 106 | 107 | #### 0.1.0.2 108 | Bug fixes 109 | 110 | #### 0.1.0.3 111 | Bug fixes 112 | 113 | #### 1.0.0.0 114 | Public release 115 | 116 | #### 1.0.0.1 117 | Added OS version check instead of KB check 118 | 119 | #### 1.0.0.2 120 | Updated the restart message after install 121 | Update the logging while uninstall 122 | 123 | #### 1.0.0.6 124 | Fixed a bug in how dockerd was being registered as a service 125 | 126 | #### 1.0.0.7 127 | Fixed a bug where system env vars would be mangled when installing/uninstalling Docker on top of another. 128 | Fixed readme instruction formatting for easier copy/paste/execute 129 | 130 | #### 1.0.0.8 131 | Fixed a bug where installation of Docker fails over a slow network connection. 132 | Added more helpful error text towards failed installation attempts on Windows 10 client machines. 133 | 134 | ### Dependencies 135 | * 1. Nuget binaries 136 | * 2. Update: KB3176936 or later needs to be installed on your machine 137 | 138 | ### Not supported scenarios 139 | * 1. We use BITs for downloading purposes. Currently the following scenarios are not supported by BITs: 140 | * 1.1. Behind a proxy 141 | * 1.2. Powershell Direct 142 | * 1.3. SSH remoting 143 | * Note: Please use WinRM based Powershell Remoting. 144 | --------------------------------------------------------------------------------