├── 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 |
--------------------------------------------------------------------------------