├── .gitattributes
├── Build.ps1
├── Deploy.PSDeploy.ps1
├── GitVersion.yml
├── License
├── Media
├── Out-GridView.png
└── PSDockerHub.png
├── PSDockerHub
├── PSDockerHub.psd1
├── PSDockerHub.psm1
├── Private
│ ├── Add-TypeName.ps1
│ ├── Invoke-DockerHubWebRequest.ps1
│ └── Resolve-DockerHubRepoName.ps1
├── Public
│ ├── Find-DockerImage.ps1
│ ├── Get-DockerImageBuildDetail.ps1
│ ├── Get-DockerImageBuildHistory.ps1
│ ├── Get-DockerImageDetail.ps1
│ ├── Get-DockerImageDockerfile.ps1
│ └── Get-DockerImageTag.ps1
├── TypeData
│ ├── PSDockerHub.Format.ps1xml
│ └── PSDockerHub.Types.ps1xml
└── en-US
│ └── about_PSDockerHub.help.txt
├── PSake.ps1
├── README.md
├── Tests
├── Find-DockerImage.Tests.ps1
├── Invoke-DockerHubWebRequest.Mock.ps1
├── PSScriptAnalyzer.Tests.ps1
└── RunAllTests.cmd
└── appveyor.yml
/.gitattributes:
--------------------------------------------------------------------------------
1 | * -text
--------------------------------------------------------------------------------
/Build.ps1:
--------------------------------------------------------------------------------
1 | # Stop on all errors
2 | $ErrorActionPreference = 'Stop'
3 |
4 | # Grab nuget bits, install modules, set build variables, start build.
5 | Get-PackageProvider -Name NuGet -ForceBootstrap | Out-Null
6 |
7 | Install-Module PSDeploy, BuildHelpers, Psake, Pester, PSScriptAnalyzer -Force -SkipPublisherCheck
8 | Import-Module Psake, BuildHelpers
9 |
10 | Set-BuildEnvironment
11 |
12 | Invoke-psake .\psake.ps1
13 | exit ( [int]( -not $psake.build_success ) )
14 |
--------------------------------------------------------------------------------
/Deploy.PSDeploy.ps1:
--------------------------------------------------------------------------------
1 | # Generic module deployment.
2 | # This stuff should be moved to psake for a cleaner deployment view
3 |
4 | # ASSUMPTIONS:
5 |
6 | # folder structure of:
7 | # - RepoFolder
8 | # - This PSDeploy file
9 | # - ModuleName
10 | # - ModuleName.psd1
11 |
12 | # Nuget key in $ENV:NugetApiKey
13 |
14 | # Set-BuildEnvironment from BuildHelpers module has populated ENV:BHProjectName
15 |
16 | # Publish to gallery with a few restrictions
17 | if(
18 | $env:BHProjectName -and $env:BHProjectName.Count -eq 1 -and
19 | $env:BHBuildSystem -ne 'Unknown' -and
20 | $env:BHBranchName -eq "master" -and
21 | $env:BHCommitMessage -match '!deploy'
22 | )
23 | {
24 | Deploy Module {
25 | By PSGalleryModule {
26 | FromSource $ENV:BHProjectName
27 | To PSGallery
28 | WithOptions @{
29 | ApiKey = $ENV:NugetApiKey
30 | }
31 | }
32 | }
33 | }
34 | else
35 | {
36 | "Skipping deployment: To deploy, ensure that...`n" +
37 | "`t* You are in a known build system (Current: $ENV:BHBuildSystem)`n" +
38 | "`t* You are committing to the master branch (Current: $ENV:BHBranchName) `n" +
39 | "`t* Your commit message includes !deploy (Current: $ENV:BHCommitMessage)" |
40 | Write-Host
41 | }
42 |
43 | # Publish to AppVeyor if we're in AppVeyor
44 | if(
45 | $env:BHProjectName -and $ENV:BHProjectName.Count -eq 1 -and
46 | $env:BHBuildSystem -eq 'AppVeyor'
47 | )
48 | {
49 | Deploy DeveloperBuild {
50 | By AppVeyorModule {
51 | FromSource $ENV:BHProjectName
52 | To AppVeyor
53 | WithOptions @{
54 | Version = $env:GitVersion_NuGetVersion
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/GitVersion.yml:
--------------------------------------------------------------------------------
1 | mode: Mainline
2 | next-version: 1.1.0
--------------------------------------------------------------------------------
/License:
--------------------------------------------------------------------------------
1 | Microsoft Public License (Ms-PL)
2 |
3 | This license governs use of the accompanying software. If you use the
4 | software, you accept this license. If you do not accept the license, do not
5 | use the software.
6 |
7 | 1. Definitions
8 |
9 | The terms "reproduce," "reproduction," "derivative works," and
10 | "distribution" have the same meaning here as under U.S. copyright law.
11 |
12 | A "contribution" is the original software, or any additions or changes to
13 | the software.
14 |
15 | A "contributor" is any person that distributes its contribution under this
16 | license.
17 |
18 | "Licensed patents" are a contributor's patent claims that read directly on
19 | its contribution.
20 |
21 | 2. Grant of Rights
22 |
23 | (A) Copyright Grant- Subject to the terms of this license, including the
24 | license conditions and limitations in section 3, each contributor grants
25 | you a non-exclusive, worldwide, royalty-free copyright license to reproduce
26 | its contribution, prepare derivative works of its contribution, and
27 | distribute its contribution or any derivative works that you create.
28 |
29 | (B) Patent Grant- Subject to the terms of this license, including the
30 | license conditions and limitations in section 3, each contributor grants
31 | you a non-exclusive, worldwide, royalty-free license under its licensed
32 | patents to make, have made, use, sell, offer for sale, import, and/or
33 | otherwise dispose of its contribution in the software or derivative works
34 | of the contribution in the software.
35 |
36 | 3. Conditions and Limitations
37 |
38 | (A) No Trademark License- This license does not grant you rights to use any
39 | contributors' name, logo, or trademarks.
40 |
41 | (B) If you bring a patent claim against any contributor over patents that
42 | you claim are infringed by the software, your patent license from such
43 | contributor to the software ends automatically.
44 |
45 | (C) If you distribute any portion of the software, you must retain all
46 | copyright, patent, trademark, and attribution notices that are present in
47 | the software.
48 |
49 | (D) If you distribute any portion of the software in source code form, you
50 | may do so only under this license by including a complete copy of this
51 | license with your distribution. If you distribute any portion of the
52 | software in compiled or object code form, you may only do so under a
53 | license that complies with this license.
54 |
55 | (E) The software is licensed "as-is." You bear the risk of using it. The
56 | contributors give no express warranties, guarantees or conditions. You may
57 | have additional consumer rights under your local laws which this license
58 | cannot change. To the extent permitted under your local laws, the
59 | contributors exclude the implied warranties of merchantability, fitness for
60 | a particular purpose and non-infringement.
61 |
--------------------------------------------------------------------------------
/Media/Out-GridView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beatcracker/PSDockerHub/36e48232fdf78ee232daba16db392a0002add72c/Media/Out-GridView.png
--------------------------------------------------------------------------------
/Media/PSDockerHub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beatcracker/PSDockerHub/36e48232fdf78ee232daba16db392a0002add72c/Media/PSDockerHub.png
--------------------------------------------------------------------------------
/PSDockerHub/PSDockerHub.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'PSDockerHub'
3 | #
4 | # Generated by: beatcracker
5 | #
6 | # Generated on: 13.07.2016
7 | #
8 |
9 | @{
10 |
11 | # Script module or binary module file associated with this manifest.
12 | RootModule = 'PSDockerHub.psm1'
13 |
14 | # Version number of this module.
15 | ModuleVersion = '1.0.0'
16 |
17 | # ID used to uniquely identify this module
18 | GUID = '4f082512-cfb9-4a4b-a420-ae6c6bf40721'
19 |
20 | # Author of this module
21 | Author = 'beatcracker'
22 |
23 | # Company or vendor of this module
24 | CompanyName = 'NA'
25 |
26 | # Copyright statement for this module
27 | Copyright = '(c) 2019 beatcracker. All rights reserved.'
28 |
29 | # Description of the functionality provided by this module
30 | Description = 'PSDockerHub is a PowerShell module written to access the official Docker Hub/Registry. Its main goal is to to make sure that you have never had to use the public part of Docker Hub site in the browser.'
31 |
32 | # Minimum version of the Windows PowerShell engine required by this module
33 | PowerShellVersion = '3.0'
34 |
35 | # Name of the Windows PowerShell host required by this module
36 | # PowerShellHostName = ''
37 |
38 | # Minimum version of the Windows PowerShell host required by this module
39 | # PowerShellHostVersion = ''
40 |
41 | # Minimum version of Microsoft .NET Framework required by this module
42 | # DotNetFrameworkVersion = ''
43 |
44 | # Minimum version of the common language runtime (CLR) required by this module
45 | # CLRVersion = ''
46 |
47 | # Processor architecture (None, X86, Amd64) required by this module
48 | # ProcessorArchitecture = ''
49 |
50 | # Modules that must be imported into the global environment prior to importing this module
51 | # RequiredModules = @()
52 |
53 | # Assemblies that must be loaded prior to importing this module
54 | # RequiredAssemblies = @()
55 |
56 | # Script files (.ps1) that are run in the caller's environment prior to importing this module.
57 | # ScriptsToProcess = @()
58 |
59 | # Type files (.ps1xml) to be loaded when importing this module
60 | TypesToProcess = @('.\TypeData\PSDockerHub.Types.ps1xml')
61 |
62 | # Format files (.ps1xml) to be loaded when importing this module
63 | FormatsToProcess = @('.\TypeData\PSDockerHub.Format.ps1xml')
64 |
65 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
66 | # NestedModules = @()
67 |
68 | # Functions to export from this module
69 | FunctionsToExport = @(
70 | 'Find-DockerImage'
71 | 'Get-DockerImageBuildDetail'
72 | 'Get-DockerImageBuildHistory'
73 | 'Get-DockerImageDetail'
74 | 'Get-DockerImageDockerfile'
75 | 'Get-DockerImageTag'
76 | )
77 |
78 | # Cmdlets to export from this module
79 | CmdletsToExport = @()
80 |
81 | # Variables to export from this module
82 | VariablesToExport = @()
83 |
84 | # Aliases to export from this module
85 | AliasesToExport = @()
86 |
87 | # DSC resources to export from this module
88 | # DscResourcesToExport = @()
89 |
90 | # List of all modules packaged with this module
91 | # ModuleList = @()
92 |
93 | # List of all files packaged with this module
94 | # FileList = @()
95 |
96 | # 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.
97 | PrivateData = @{
98 |
99 | PSData = @{
100 |
101 | # Tags applied to this module. These help with module discovery in online galleries.
102 | Tags = @('Docker', 'Hub', 'Container', 'API', 'Find', 'Search')
103 |
104 | # A URL to the license for this module.
105 | LicenseUri = 'https://github.com/beatcracker/PSDockerHub/blob/master/License'
106 |
107 | # A URL to the main website for this project.
108 | ProjectUri = 'https://github.com/beatcracker/PSDockerHub'
109 |
110 | # A URL to an icon representing this module.
111 | IconUri = 'https://raw.githubusercontent.com/beatcracker/PSDockerHub/master/Media/PSDockerHub.png'
112 |
113 | # ReleaseNotes of this module
114 | ReleaseNotes = "Quick fix to make module work, no new features added."
115 |
116 | } # End of PSData hashtable
117 |
118 | } # End of PrivateData hashtable
119 |
120 | # HelpInfo URI of this module
121 | # HelpInfoURI = ''
122 |
123 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
124 | # DefaultCommandPrefix = ''
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/PSDockerHub/PSDockerHub.psm1:
--------------------------------------------------------------------------------
1 | $script:FunctionsToExport = @()
2 | $Folders = 'Public', 'Private'
3 |
4 | foreach ($Scope in $Folders) {
5 | Get-ChildItem -LiteralPath (
6 | Join-Path -Path $PSScriptRoot -ChildPath $Scope
7 | ) -File -Filter '*.ps1' | ForEach-Object {
8 | $File = $_
9 | try {
10 | Write-Verbose "Dotsourcing file: $File"
11 | . $File.FullName
12 |
13 | switch ($Scope) {
14 | 'Public' {
15 | $script:FunctionsToExport += $File.BaseName
16 | }
17 | }
18 | } catch {
19 | throw "Can't import functions from file: $File"
20 | }
21 | }
22 | }
23 |
24 | Export-ModuleMember -Function $script:FunctionsToExport
--------------------------------------------------------------------------------
/PSDockerHub/Private/Add-TypeName.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Adds TypeName to piped object
4 |
5 | .Parameter TypeName
6 | String array of typenames
7 | #>
8 | filter Add-TypeName {
9 | Param([string[]]$TypeName)
10 | foreach ($name in $TypeName) {
11 | $_.PSObject.TypeNames.Insert(0, $name)
12 | }
13 | $_
14 | }
--------------------------------------------------------------------------------
/PSDockerHub/Private/Invoke-DockerHubWebRequest.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Helper function to query Docker Hub API.
4 |
5 | .Description
6 | Helper function to query Docker Hub API.
7 | Supports singular and paginated requests.
8 |
9 | .Parameter Request
10 | Request part of the URL, e.g.: 'search/repositories/?query=alpine'
11 |
12 | .Parameter Paginated
13 | Make paginated request. Automatically requests URL for a next page (Docker Hub API returns it as a part of responce).
14 |
15 | .Parameter UsePageSize
16 | Hint function, that endpoint supports 'page_size' parameter and it should be used.
17 |
18 | .Parameter PageSize
19 | Sets page size to use, if endpoint supports 'page_size' parameter
20 |
21 | .Parameter MaxResults
22 | Maximum number of results to return, if request is paginated.
23 | #>
24 | function Invoke-DockerHubWebRequest
25 | {
26 | [CmdletBinding(DefaultParameterSetName = 'Single')]
27 | Param
28 | (
29 | [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Single')]
30 | [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Paginated')]
31 | [ValidateNotNullOrEmpty()]
32 | [string[]]$Request,
33 |
34 | [Parameter(Mandatory = $true, ParameterSetName = 'Paginated')]
35 | [switch]$Paginated,
36 |
37 | [Parameter(ParameterSetName = 'Paginated')]
38 | [Parameter(ParameterSetName = 'PageSize')]
39 | [switch]$UsePageSize,
40 |
41 | [Parameter(ParameterSetName = 'Paginated')]
42 | [Parameter(ParameterSetName = 'PageSize')]
43 | [int]$PageSize = 100,
44 |
45 | [Parameter(ParameterSetName = 'Paginated')]
46 | [int]$MaxResults = [int]::MaxValue
47 | )
48 |
49 | Begin
50 | {
51 | $DockerHub = 'https://hub.docker.com'
52 | $ApiVersion = 'v2'
53 | $PageSizeParam = 'page_size={0}'
54 | }
55 |
56 | Process
57 | {
58 | foreach ($item in $Request) {
59 | [uri]$Uri = ($DockerHub, $ApiVersion ,$item) -join '/'
60 |
61 | if ($Paginated) {
62 | if ($UsePageSize) {
63 | if ($Uri.Query) {
64 | $Joiner = '&'
65 | } else {
66 | $Joiner = '?'
67 | }
68 |
69 | if($MaxResults -lt $PageSize) {
70 | $PageSize = $MaxResults
71 | }
72 |
73 | [uri]$Uri = ($Uri, ($PageSizeParam -f $PageSize)) -join $Joiner
74 | }
75 |
76 | Write-Verbose "Making paginated request to DockerHub API: $Uri"
77 | $ResultsCount = 0
78 |
79 | while ($Uri) {
80 | try {
81 | $Response = (Invoke-WebRequest -Uri $Uri -UseBasicParsing -ErrorAction Stop).Content
82 | } catch {
83 | throw $_
84 | }
85 |
86 | if ($Response) {
87 | try {
88 | $ret = $Response | ConvertFrom-Json -ErrorAction Stop
89 | } catch{
90 | throw $_
91 | }
92 |
93 | $ResultsCount += $ret.results.Count
94 |
95 | 'Page size: {0}. Total items available: {1}. Total items received : {2}. Items received in this batch: {3}. ' -f (
96 | ($false, $PageSize)[[bool]$UsePageSize],
97 | $ret.count,
98 | $ResultsCount,
99 | $ret.results.Count
100 | ) | Write-Verbose
101 |
102 | 'Next result uri: {0}' -f $ret.next | Write-Verbose
103 |
104 | if ($ResultsCount -gt $MaxResults) {
105 | $Uri = $null
106 | $SkipCount = $ResultsCount - $MaxResults
107 | Write-Verbose "Results limit reached, skipping last: $SkipCount"
108 | $ret.results | Select-Object -SkipLast $SkipCount
109 | } else {
110 | $NextUri = $null
111 |
112 | if (-not [System.String]::IsNullOrEmpty($ret.next)) {
113 | if([uri]::TryCreate($ret.next, [System.UriKind]::Absolute, [ref]$NextUri)) {
114 | if ($NextUri.Host -ne $Uri.Host) {
115 | $UriBuilder = New-Object -TypeName System.UriBuilder -ArgumentList $NextUri
116 | $UriBuilder.Host = $Uri.Host
117 | $NextUri = $UriBuilder.ToString()
118 | Write-Verbose "Fixing url for next result: $NextUri -> $Uri"
119 | }
120 | }
121 | }
122 |
123 | $Uri = $NextUri
124 | $ret.results
125 | }
126 | }
127 | }
128 | } else {
129 | Write-Verbose "Making singular request to DockerHub API: $Uri"
130 | try {
131 | $Response = (Invoke-WebRequest -Uri $Uri -UseBasicParsing -ErrorAction Stop).Content
132 | } catch {
133 | throw $_
134 | }
135 |
136 | if ($Response) {
137 | $Response | ConvertFrom-Json -ErrorAction Stop
138 | }
139 | }
140 | }
141 | }
142 | }
--------------------------------------------------------------------------------
/PSDockerHub/Private/Resolve-DockerHubRepoName.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Adds 'library' path component to the piped name, if it has only one path component.
4 | Used to resolve names for official repositories like 'alpine' and 'mariadb'.
5 |
6 | .Link
7 | https://docs.docker.com/registry/spec/api/
8 | #>
9 | filter Resolve-DockerHubRepoName {
10 | if ($_ -match '/') {
11 | $_
12 | } else {
13 | "library/$_"
14 | }
15 | }
--------------------------------------------------------------------------------
/PSDockerHub/Public/Find-DockerImage.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Search for docker images on Docker Hub
4 |
5 | .Description
6 | Search for docker images on Docker Hub via Docker Hub API.
7 | You can filter search by Name/Description, Stars, Downloads, Official images and Automated builds.
8 |
9 | .Parameter SearchTerm
10 | Search term. Docker Hub will search it in the Name and Description.
11 | If search term is not specified, function will return all available images using wildcard query ('*').
12 |
13 | .Parameter SortBy
14 | Sort by Downloads or Stars. Sorting is performed on Docker Hub side.
15 |
16 | .Parameter Automated
17 | Search only for automated builds
18 | Note, that this parameter is not available, when SearchTerm is omitted (wildcard query)
19 |
20 | .Parameter Official
21 | Search only for official images
22 | Note, that this parameter is not available, when SearchTerm is omitted (wildcard query)
23 |
24 | .Parameter MaxResults
25 | Maximum number of results to return. Default is 25.
26 |
27 | .Example
28 | Find-DockerImage -SearchTerm mariadb -Official
29 |
30 | Search for official MariaDB docker images
31 |
32 | .Example
33 | Find-DockerImage -SearchTerm ruby -SortBy Stars -Automated -MaxResults 5
34 |
35 | Search for automated builds of 'ruby', sort by stars, return 5 top results
36 |
37 | .Example
38 | Find-DockerImage -SearchTerm mariadb -SortBy Downloads | Where-Object {$_.Name -like '*alpine*'}
39 |
40 | Search for MariaDB docker images, sort by downloads. Then find images built on Alpine Linux using PowerShell filtering.
41 |
42 | .Example
43 | Find-DockerImage -SortBy Downloads
44 |
45 | Get most downloaded docker images
46 |
47 |
48 | .Example
49 | Find-DockerImage -SortBy Stars
50 |
51 | Get most starred docker images
52 | #>
53 | function Find-DockerImage
54 | {
55 | [CmdletBinding(DefaultParameterSetName = '__AllParameterSets')]
56 | Param
57 | (
58 | [Parameter(Position = 0, ValueFromPipeline = $true)]
59 | [string[]]$SearchTerm,
60 |
61 | [Parameter(Position = 1)]
62 | [ValidateSet('Downloads', 'Stars')]
63 | [string]$SortBy,
64 |
65 | [Parameter(Position = 2, ParameterSetName = 'SearchTerm_Automated')]
66 | [switch]$Automated,
67 |
68 | [Parameter(Position = 2, ParameterSetName = 'SearchTerm_Official')]
69 | [switch]$Official,
70 |
71 | [Parameter(Position = 3)]
72 | [int]$MaxResults = 25
73 | )
74 |
75 | Begin
76 | {
77 | $RequestTpl = 'search/repositories/?query={0}'
78 | $QueryParamMap = @{
79 | Automated = 'is_automated=1'
80 | Official = 'is_official=1'
81 | Downloads = 'ordering=-pull_count'
82 | Stars = 'ordering=-star_count'
83 | }
84 | }
85 |
86 | Process
87 | {
88 | $SearchTerm = $SearchTerm -replace '^$', '*'
89 |
90 | $QueryParams = @()
91 |
92 | if ($Automated) {
93 | $QueryParams += $QueryParamMap.Automated
94 | }
95 |
96 | if ($Official) {
97 | $QueryParams += $QueryParamMap.Official
98 | }
99 |
100 | if ($SortBy) {
101 | $QueryParams += $QueryParamMap.$SortBy
102 | }
103 |
104 | $Request = $SearchTerm | ForEach-Object {
105 | (
106 | @($RequestTpl -f [System.Net.WebUtility]::UrlEncode($_)) + $QueryParams
107 | ) -join '&'
108 | }
109 |
110 | Invoke-DockerHubWebRequest -Request $Request -Paginated -UsePageSize -MaxResults $MaxResults |
111 | Select-Object -Property (
112 | @{n = 'Name' ; e = {$_.repo_name}},
113 | @{n = 'Description' ; e = {$_.short_description}},
114 | @{n = 'Stars' ; e = {$_.star_count}},
115 | @{n = 'Downloads' ; e = {$_.pull_count}},
116 | @{n = 'Official' ; e = {$_.is_official}},
117 | @{n = 'Automated' ; e = {$_.is_automated}}
118 | ) | Add-TypeName -TypeName $PSCmdlet.MyInvocation.MyCommand.Name
119 | }
120 | }
--------------------------------------------------------------------------------
/PSDockerHub/Public/Get-DockerImageBuildDetail.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Get Docker image build details
4 |
5 | .Description
6 | Get Docker image build details
7 | Build history is available only for some automated builds.
8 |
9 | .Parameter Name
10 | Docker repository (image) name
11 |
12 | .Parameter MaxResults
13 | Maximum number of results to return. Default is 100.
14 |
15 | .Example
16 | Get-DockerImageBuildDetail -Name 'jwilder/nginx-proxy'
17 |
18 | Get build details for 'jwilder/nginx-proxy' image
19 | #>
20 | function Get-DockerImageBuildDetail
21 | {
22 | [CmdletBinding()]
23 | Param
24 | (
25 | [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
26 | [ValidateNotNullOrEmpty()]
27 | [string[]]$Name
28 | )
29 |
30 | Begin
31 | {
32 | $RequestTpl = 'repositories/{0}/autobuild/'
33 | }
34 |
35 | Process
36 | {
37 | foreach ($item in $Name) {
38 | $Request = $RequestTpl -f ($item | Resolve-DockerHubRepoName)
39 | (Invoke-DockerHubWebRequest -Request $Request) | Select-Object -Property (
40 | @{n = 'Name' ; e = {$_.build_name}},
41 | @{n = 'Provider' ; e = {$_.provider}},
42 | @{n = 'Type' ; e = {$_.repo_type}},
43 | @{n = 'Url' ; e = {$_.repo_web_url}},
44 | @{n = 'Repo' ; e = {$_.source_url}},
45 | @{n = 'Tags' ; e = {
46 | $_.build_tags | Select-Object -Property (
47 | @{n = 'Name' ; e = {$_.name}},
48 | @{n = 'Source' ; e = {$_.source_name}},
49 | @{n = 'Type' ; e = {$_.source_type}},
50 | @{n = 'Dockerfile' ; e = {$_.dockerfile_location}},
51 | @{n = 'Id' ; e = {$_.id}}
52 | ) | Add-TypeName -TypeName ($PSCmdlet.MyInvocation.MyCommand.Name + '-Tags')
53 | }}
54 | ) | Add-TypeName -TypeName $PSCmdlet.MyInvocation.MyCommand.Name
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/PSDockerHub/Public/Get-DockerImageBuildHistory.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Get Docker image build history
4 |
5 | .Description
6 | Get Docker image build history
7 | Build history is available only for some automated builds.
8 |
9 | .Parameter Name
10 | Docker repository (image) name
11 |
12 | .Parameter MaxResults
13 | Maximum number of results to return. Default is 100.
14 |
15 | .Example
16 | Get-DockerImageBuildHistory -Name 'jwilder/nginx-proxy'
17 |
18 | Get build history for 'jwilder/nginx-proxy' image
19 | #>
20 | function Get-DockerImageBuildHistory
21 | {
22 | [CmdletBinding()]
23 | Param
24 | (
25 | [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
26 | [ValidateNotNullOrEmpty()]
27 | [string[]]$Name,
28 |
29 | [int]$MaxResults = 100
30 | )
31 |
32 | Begin
33 | {
34 | $RequestTpl = 'repositories/{0}/buildhistory/'
35 |
36 | # https://github.com/badges/shields/issues/241
37 | $StatusMap = @{
38 | 0 = 'Queued'
39 | -1 = 'Error'
40 | 3 = 'Building'
41 | 10 = 'Success'
42 | }
43 | }
44 |
45 | Process
46 | {
47 | $Request = $Name | ForEach-Object {
48 | $RequestTpl -f ($_ | Resolve-DockerHubRepoName)
49 | }
50 |
51 | Invoke-DockerHubWebRequest -Request $Request -Paginated -UsePageSize -MaxResults $MaxResults |
52 | Select-Object -Property (
53 | @{n = 'Tag' ; e = {$_.dockertag_name}},
54 | @{n = 'Status' ; e = {$StatusMap.($_.status)}},
55 | @{n = 'Id' ; e = {$_.id}},
56 | @{n = 'BuildCode' ; e = {$_.build_code}},
57 | @{n = 'Cause' ; e = {$_.cause}},
58 | @{n = 'Created' ; e = {[Nullable[DateTime]]$_.created_date}},
59 | @{n = 'Updated' ; e = {[Nullable[DateTime]]$_.last_updated}}
60 | ) | Add-TypeName -TypeName $PSCmdlet.MyInvocation.MyCommand.Name
61 | }
62 | }
--------------------------------------------------------------------------------
/PSDockerHub/Public/Get-DockerImageDetail.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Get detailed information for a Docker image.
4 |
5 | .Description
6 | Get detailed information for a Docker image, including full description in markdown.
7 |
8 | .Parameter Name
9 | Docker repository (image) name
10 |
11 | .Example
12 | Get-DockerImageDetail -Name 'mariadb'
13 |
14 | .Example
15 | 'alpine' | Get-DockerImageDetail
16 | #>
17 | function Get-DockerImageDetail
18 | {
19 | [CmdletBinding()]
20 | Param
21 | (
22 | [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
23 | [ValidateNotNullOrEmpty()]
24 | [string[]]$Name
25 | )
26 |
27 | Begin
28 | {
29 | $RequestTpl = 'repositories/{0}/'
30 | }
31 |
32 | Process
33 | {
34 | foreach ($item in $Name) {
35 | $Request = $RequestTpl -f ($item | Resolve-DockerHubRepoName)
36 | (Invoke-DockerHubWebRequest -Request $Request) | Select-Object -Property (
37 | @{n = 'Name' ; e = {$_.name}},
38 | @{n = 'Owner' ; e = {$_.user}},
39 | @{n = 'Description' ; e = {$_.description}},
40 | @{n = 'Active' ; e = {[bool]$_.status}},
41 | @{n = 'Updated' ; e = {[Nullable[DateTime]]$_.last_updated}},
42 | @{n = 'Private' ; e = {$_.is_private}},
43 | @{n = 'Stars' ; e = {$_.star_count}},
44 | @{n = 'Downloads' ; e = {$_.pull_count}},
45 | @{n = 'Official' ; e = {if ($_.namespace -eq 'library') {$true} else {$false}}},
46 | @{n = 'Automated' ; e = {$_.is_automated}},
47 | @{n = 'FullDescription' ; e = {$_.full_description}}
48 | )
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/PSDockerHub/Public/Get-DockerImageDockerfile.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Get Docker image Dockerfile.
4 |
5 | .Description
6 | Get Docker image Dockerfile.
7 | Build history is available only for some automated builds.
8 |
9 | .Parameter Name
10 | Docker repository (image) name
11 |
12 | .Example
13 | Get-DockerImageDockerfile -Name 'jwilder/nginx-proxy'
14 |
15 | Get Dockerfile for 'jwilder/nginx-proxy' image
16 |
17 | #>
18 | function Get-DockerImageDockerfile
19 | {
20 | [CmdletBinding()]
21 | Param
22 | (
23 | [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
24 | [ValidateNotNullOrEmpty()]
25 | [string[]]$Name
26 | )
27 |
28 | Begin
29 | {
30 | $RequestTpl = 'repositories/{0}/dockerfile/'
31 | }
32 |
33 | Process
34 | {
35 | foreach ($item in $Name) {
36 | $Request = $RequestTpl -f ($item | Resolve-DockerHubRepoName)
37 | (Invoke-DockerHubWebRequest -Request $Request).contents
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/PSDockerHub/Public/Get-DockerImageTag.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .Synopsis
3 | Get Docker image tags for image
4 |
5 | .Description
6 | Get Docker image tags for image via Docker Hub API
7 |
8 | .Parameter Name
9 | Docker repository (image) name
10 |
11 | .Parameter MaxResults
12 | Maximum number of results to return. Default is 100.
13 |
14 | .Example
15 | Get-DockerImageTag -Name 'mariadb'
16 |
17 | Get tags for 'mariadb' image
18 |
19 | .Example
20 | Find-DockerImage 'alpine' -Official | Get-DockerImageTag
21 |
22 | Search for official Alpine Linux docker image, then get its tags.
23 |
24 | #>
25 | function Get-DockerImageTag
26 | {
27 | [CmdletBinding()]
28 | Param
29 | (
30 | [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
31 | [ValidateNotNullOrEmpty()]
32 | [string[]]$Name,
33 |
34 | [int]$MaxResults = 100
35 | )
36 |
37 | Begin
38 | {
39 | $RequestTpl = 'repositories/{0}/tags/'
40 | }
41 |
42 | Process
43 | {
44 | $Request = $Name | ForEach-Object {
45 | $RequestTpl -f ($_ | Resolve-DockerHubRepoName)
46 | }
47 |
48 | Invoke-DockerHubWebRequest -Request $Request -Paginated -UsePageSize -MaxResults $MaxResults |
49 | Select-Object -Property (
50 | @{n = 'Name' ; e = {$_.name}},
51 | @{n = 'Size' ; e = {$_.full_size}},
52 | @{n = 'Updated' ; e = {[Nullable[DateTime]]$_.last_updated}},
53 | @{n = 'Id' ; e = {$_.id}}
54 | ) | Add-TypeName -TypeName $PSCmdlet.MyInvocation.MyCommand.Name
55 | }
56 | }
--------------------------------------------------------------------------------
/PSDockerHub/TypeData/PSDockerHub.Format.ps1xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Get-DockerImageBuildDetail-GroupingFormat
6 |
7 |
8 |
9 |
10 | Name :
11 |
12 | Name
13 |
14 |
15 | Provider :
16 |
17 | Provider
18 |
19 |
20 | Type :
21 |
22 | Type
23 |
24 |
25 | Repo :
26 |
27 | Repo
28 |
29 |
30 | Url :
31 |
32 | Url
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | FindDockerImageView
45 |
46 | Find-DockerImage
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | Left
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Name
76 |
77 |
78 | Description
79 |
80 |
81 | Stars
82 | Right
83 |
84 |
85 | Downloads
86 | Right
87 |
88 |
89 | Official
90 | Right
91 |
92 |
93 | Automated
94 | Right
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | GetDockerImageTagView
103 |
104 | Get-DockerImageTag
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | Right
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | Name
127 |
128 |
129 | '{0} MB' -f [math]::Round($_.Size / 1MB)
130 |
131 |
132 | Updated
133 |
134 |
135 | Id
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | GetDockerImageTagView
144 |
145 | Get-DockerImageTag
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | Right
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | Name
168 |
169 |
170 | '{0} MB' -f [math]::Round($_.Size / 1MB)
171 |
172 |
173 | Updated
174 |
175 |
176 | Id
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | GetDockerImageBuildDetailView
185 |
186 | Get-DockerImageBuildDetail-Tags
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 | Name
211 |
212 |
213 | Source
214 |
215 |
216 | Type
217 |
218 |
219 | Dockerfile
220 |
221 |
222 | Id
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 | GetDockerImageBuildDetailView
231 |
232 | Get-DockerImageBuildDetail
233 |
234 |
235 | Name
236 | Get-DockerImageBuildDetail-GroupingFormat
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 | ($_.Tags | Out-String).Trim()
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
--------------------------------------------------------------------------------
/PSDockerHub/TypeData/PSDockerHub.Types.ps1xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Find-DockerImage
4 |
5 |
6 | PSStandardMembers
7 |
8 |
9 | DefaultDisplayPropertySet
10 |
11 | Name
12 | Description
13 | Stars
14 | Downloads
15 | Official
16 | Automated
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Get-DockerImageTag
25 |
26 |
27 | PSStandardMembers
28 |
29 |
30 | DefaultDisplayPropertySet
31 |
32 | Name
33 | Size
34 | Updated
35 | Id
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | Get-DockerImageBuildDetail
44 |
45 |
46 | PSStandardMembers
47 |
48 |
49 | DefaultDisplayPropertySet
50 |
51 | Name
52 | Provider
53 | Type
54 | Url
55 | Repo
56 | Tags
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/PSDockerHub/en-US/about_PSDockerHub.help.txt:
--------------------------------------------------------------------------------
1 | PSTOPIC
2 | about_PSDockerHub
3 |
4 | SHORT DESCRIPTION
5 | PSDockerHub is a PowerShell module written to access the official Docker Hub/Registry
6 |
7 | LONG DESCRIPTION
8 | PSDockerHub is a PowerShell module written to access the official Docker Hub/Registry.
9 | Its main goal is to to make sure that you have never had to use the public part of Docker Hub site in the browser.
10 |
11 | Most of the APIs used were sniffed using the Chrome DevTools,
12 | because there is significant fragmentation of APIs between the various Docker offerings.
13 |
14 | You can find API documentation here:
15 |
16 | * https://docs.docker.com/registry/spec/api/
17 |
18 | Search is not documented and the best I could find is this:
19 |
20 | * http://stackoverflow.com/questions/35444178/public-docker-v2-api-endpoints
21 | * https://github.com/docker/hub-feedback/issues/451
22 |
23 | Please note, that at the moment I have no plans to introduce support of authorization and private repositories.
24 |
25 | Suggestions, pull requests, and other contributions would be more than welcome!
--------------------------------------------------------------------------------
/PSake.ps1:
--------------------------------------------------------------------------------
1 | # PSake makes variables declared here available in other scriptblocks
2 | # Init some things
3 | Properties {
4 | # Find the build folder based on build system
5 | $ProjectRoot = $ENV:BHProjectPath
6 | if(-not $ProjectRoot)
7 | {
8 | $ProjectRoot = $PSScriptRoot
9 | }
10 |
11 | $Timestamp = Get-date -uformat "%Y%m%d-%H%M%S"
12 | $PSVersion = $PSVersionTable.PSVersion.Major
13 | $TestFile = "TestResults_PS$PSVersion`_$TimeStamp.xml"
14 | $lines = '----------------------------------------------------------------------'
15 |
16 | $Verbose = @{}
17 | if($ENV:BHCommitMessage -match "!verbose")
18 | {
19 | $Verbose = @{Verbose = $True}
20 | }
21 | }
22 |
23 | Task Default -Depends Deploy
24 |
25 | Task Init {
26 | $lines
27 | Set-Location $ProjectRoot
28 | "Build System Details:"
29 | Get-Item ENV:BH*
30 | "`n"
31 | }
32 |
33 | Task Test -Depends Init {
34 | $lines
35 | "`n`tSTATUS: Testing with PowerShell $PSVersion"
36 |
37 | # Gather test results. Store them in a variable and file
38 | $TestResults = Invoke-Pester -Path $ProjectRoot\Tests -PassThru -OutputFormat NUnitXml -OutputFile "$ProjectRoot\$TestFile"
39 |
40 | # In Appveyor? Upload our tests! #Abstract this into a function?
41 | If($ENV:BHBuildSystem -eq 'AppVeyor')
42 | {
43 | (New-Object 'System.Net.WebClient').UploadFile(
44 | "https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)",
45 | "$ProjectRoot\$TestFile" )
46 | }
47 |
48 | Remove-Item "$ProjectRoot\$TestFile" -Force -ErrorAction SilentlyContinue
49 |
50 | # Failed tests?
51 | # Need to tell psake or it will proceed to the deployment. Danger!
52 | if($TestResults.FailedCount -gt 0)
53 | {
54 | Write-Error "Failed '$($TestResults.FailedCount)' tests, build failed"
55 | }
56 | "`n"
57 | }
58 |
59 | Task Build -Depends Test {
60 | $lines
61 |
62 | # Load the module, read the exported functions, update the psd1 FunctionsToExport
63 | Set-ModuleFunctions
64 |
65 | # Set the module version
66 | Update-Metadata -Path $env:BHPSModuleManifest -PropertyName ModuleVersion -Value $env:GitVersion_NuGetVersion
67 | }
68 |
69 | Task Deploy -Depends Build {
70 | $lines
71 |
72 | $Params = @{
73 | Path = $ProjectRoot
74 | Force = $true
75 | Recurse = $false # We keep psdeploy artifacts, avoid deploying those : )
76 | }
77 | Invoke-PSDeploy @Verbose @Params
78 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | |AppVeyor|PowerShell Gallery|
2 | |:-:|:-:|
3 | |[](https://ci.appveyor.com/project/beatcracker/psdockerhub)|[](https://www.powershellgallery.com/packages/PSDockerHub)|
4 |
5 | # `PSDockerHub`
6 |
7 | PSDockerHub is a PowerShell module written to access the official [Docker Hub/Registry](https://hub.docker.com). Its main goal is to to make sure that you have never had to use the public part of Docker Hub site in the browser.
8 |
9 | Most of the APIs used were sniffed using the Chrome DevTools, because there is [significant fragmentation](https://github.com/ngageoint/seed/blob/7ae36873dab9ea46369826a8debb666ef454aa26/detail.adoc#discovery) of APIs between the various Docker offerings.
10 |
11 | You can find API documentation here:
12 |
13 | * [Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api/)
14 |
15 | Search API is not documented and, the best I could find is this:
16 |
17 | * [Public Docker v2 API Endpoints](http://stackoverflow.com/questions/35444178/public-docker-v2-api-endpoints)
18 | * [docker/hub-feedback: Search uses OR instead of AND to combine terms](https://github.com/docker/hub-feedback/issues/451)
19 |
20 | Please note, that at the moment I have no plans to introduce support of authorization and private repositories.
21 |
22 | Suggestions, pull requests and other contributions would be more than welcome!
23 |
24 | # Requirements
25 |
26 | * PowerShell 3.0 or higher
27 |
28 | # Instructions
29 |
30 | ## Installation
31 |
32 | ### From [PowerShell Gallery](https://www.powershellgallery.com/)
33 |
34 | If you have PowerShell 5, or the PowerShellGet module ([MSI Installer for PowerShell 3 and 4](http://go.microsoft.com/fwlink/?LinkID=746217&clcid=0x409)):
35 |
36 | ```posh
37 | Install-Module PSDockerHub
38 | ```
39 |
40 | ### From GitHub repo
41 |
42 | 1. Download the repository
43 | 2. Unblock the zip
44 | 3. Extract the `PSDockerHub` folder to a module path (e.g. `$env:USERPROFILE\Documents\WindowsPowerShell\Modules\`)
45 |
46 | ## Usage
47 |
48 | ```posh
49 | # Import the module
50 | Import-Module PSDockerHub
51 |
52 | #Alternatively
53 | Import-Module \\Path\To\PSDockerHub
54 |
55 | # Get commands in the module
56 | Get-Command -Module PSDockerHub
57 |
58 | # Get help
59 | Get-Help Find-DockerImage -Full
60 | Get-Help about_PSDockerHub
61 | ```
62 |
63 | # Functions
64 |
65 | * [Find-DockerImage](#find-dockerimage)
66 | * [Get-DockerImageDetail](#get-dockerimagedetail)
67 | * [Get-DockerImageTag](#get-dockerimagetag)
68 | * [Get-DockerImageBuildDetail](#get-dockerimagebuilddetail)
69 | * [Get-DockerImageBuildHistory](#get-dockerimagebuildhistory)
70 | * [Get-DockerImageDockerfile](#get-dockerimagedockerfile)
71 |
72 | ## Find-DockerImage
73 |
74 | Search for docker images on Docker Hub via Docker Hub API. You can filter search by `Name/Description`, `Stars`, `Downloads`, `Official` images and `Automated` builds.
75 |
76 | ### Example
77 |
78 | #### Search for [MariaDB](https://mariadb.org) docker images, sort by downloads. Then find images built on [Alpine Linux](https://www.alpinelinux.org) using PowerShell filtering
79 |
80 | ```posh
81 | 'mariadb' | Find-DockerImage -SortBy Downloads -MaxResults 100 | ? Name -Like '*alpine*'
82 | ```
83 |
84 | ```no-highlight
85 | Name Description Stars Downloads Official Automated
86 | ---- ----------- ----- --------- -------- ---------
87 | wodby/mariadb-alpine mariadb-alpine 1 6533 False True
88 | k0st/alpine-mariadb MariaDB/MySQL on Alpine (size: ~154 MB) 3 2939 False True
89 | dydx/alpine-mariadb 1 671 False True
90 | timhaak/docker-maria docker mariadb using alpine 2 357 False True
91 | db-alpine
92 | ```
93 |
94 | Or you can pipe output to `Out-GridView` and apply filters there:
95 |
96 | ```powershell
97 | 'mariadb' | Find-DockerImage -SortBy Downloads -MaxResults 100 | Out-GridView
98 | ```
99 |
100 | 
101 |
102 | #### Get most downloaded docker images:
103 |
104 | ```posh
105 | Find-DockerImage -SortBy Downloads
106 | ```
107 |
108 | #### Get most starred docker images:
109 |
110 | ```posh
111 | Find-DockerImage -SortBy Stars
112 | ```
113 |
114 | ## Get-DockerImageDetail
115 |
116 | Get detailed information for a Docker image, including full description in markdown.
117 |
118 | ### Example
119 |
120 | ```posh
121 | 'zzrot/whale-awkward' | Get-DockerImageDetail
122 | ```
123 |
124 | ```no-highlight
125 | Name : whale-awkward
126 | Owner : zzrot
127 | Description : Whale, this is awkward
128 | Active : True
129 | Updated : 07.04.2016 10:15:54
130 | Private : False
131 | Stars : 2
132 | Downloads : 216653529
133 | Official : False
134 | Automated : False
135 | FullDescription : # Whale Awkward
136 | [](https://hub.d
137 | ocker.com/r/zzrot/whale-awkward/)
138 |
139 |
140 | Welcome to Whale Awkward! This is a project created by the team at [ZZROT](https://zzrot.com
141 | ). We decided it would be fun to build a simple image with a message, and then see how high
142 | we could get it on [Docker-Hub](https://hub.docker.com/).
143 |
144 | We are currently [ranked 8th](https://hub.docker.com/search/?isAutomated=0&isOfficial=0&page
145 | =1&pullCount=1&q=%22%22&starCount=0) amongst all time pulls! [Check it out](https://hub.dock
146 | er.com/r/zzrot/whale-awkward/) for yourself.
147 |
148 | Whale Awkward can be found on [Github](https://github.com/ZZROTDesign/whale-awkward)
149 |
150 | Whale Awkward was developed by:
151 | - [Sean Kilgarriff](https://seankilgarriff.com)
152 | - [Killian Brackey](https://killianbrackey.com)
153 |
154 | Through [ZZROT](https://zzrot.com) - [Github](https://github.com/ZZROTDesign)
155 | ```
156 |
157 | ## Get-DockerImageTag
158 |
159 | Get Docker image tags for image.
160 |
161 | ### Example
162 |
163 | ```posh
164 | 'alpine' | Get-DockerImageTag
165 | ```
166 |
167 | ```no-highlight
168 | Name Size Updated Id
169 | ---- ---- ------- --
170 | edge 2 MB 23.06.2016 22:56:45 170603
171 | latest 2 MB 23.06.2016 22:56:28 170608
172 | 3.4 2 MB 23.06.2016 22:56:22 3272293
173 | 3.3 2 MB 23.06.2016 22:56:10 1622498
174 | 3.2 2 MB 23.06.2016 22:55:56 170604
175 | 3.1 2 MB 23.06.2016 22:55:39 170605
176 | 2.7 2 MB 02.02.2016 22:50:30 170606
177 | 2.6 2 MB 02.02.2016 22:50:22 170607
178 | ```
179 |
180 | ## Get-DockerImageBuildDetail
181 |
182 | Get Docker image build details. Build details are available only for some [automated builds](https://docs.docker.com/docker-hub/builds/).
183 |
184 | ### Example
185 |
186 | ```posh
187 | 'jwilder/nginx-proxy' | Get-DockerImageBuildDetail
188 | ```
189 |
190 | ```no-highlight
191 | Name : jwilder/nginx-proxy
192 | Provider : github
193 | Type : git
194 | Repo : git://github.com/jwilder/nginx-proxy.git
195 | Url : https://github.com/jwilder/nginx-proxy
196 |
197 | Tags :
198 | ----------
199 | Name Source Type Dockerfile Id
200 | ---- ------ ---- ---------- --
201 | 0.3.0 0.3.0 Tag / 284672
202 | 0.4.0 0.4.0 Branch / 317837
203 | 0.2.0 0.2.0 Tag / 143192
204 | 0.1.0 0.1.0 Tag / 119443
205 | latest master Branch / 13991
206 | ```
207 |
208 | ## Get-DockerImageBuildHistory
209 |
210 | Get Docker image build history. Build history is available only for some [automated builds](https://docs.docker.com/docker-hub/builds/).
211 |
212 | ### Example
213 |
214 | ```posh
215 | 'jwilder/nginx-proxy' | Get-DockerImageBuildHistory
216 | ```
217 |
218 | ```no-highlight
219 | Tag : latest
220 | Status : Success
221 | Id : 5581215
222 | BuildCode : ba9fsgpkffixp8udcxdjp2j
223 | Cause : VCS_CHANGE
224 | Created : 13.06.2016 17:18:12
225 | Updated : 13.06.2016 17:24:31
226 |
227 | Tag : latest
228 | Status : Success
229 | Id : 5575244
230 | BuildCode : bxvykrwfncpdhzsoypmajme
231 | Cause : VCS_CHANGE
232 | Created : 13.06.2016 9:21:40
233 | Updated : 13.06.2016 9:23:47
234 |
235 | Tag : 0.4.0
236 | Status : Success
237 | Id : 5574427
238 | BuildCode : bcppfp2jtnt4s7ke2dhztrb
239 | Cause : TRIGGERED_VIA_API
240 | Created : 13.06.2016 6:45:57
241 | Updated : 13.06.2016 6:47:43
242 | ```
243 |
244 | ## Get-DockerImageDockerfile
245 |
246 | Get Docker image [Dockerfile](https://docs.docker.com/engine/reference/builder/). Dockerfiles are available only for some [automated builds](https://docs.docker.com/docker-hub/builds/).
247 |
248 | ### Example
249 |
250 | ```posh
251 | 'jwilder/nginx-proxy' | Get-DockerImageDockerfile
252 | ```
253 |
254 | ```no-highlight
255 | FROM nginx:1.9.15
256 | MAINTAINER Jason Wilder mail@jasonwilder.com
257 |
258 | # Install wget and install/updates certificates
259 | RUN apt-get update \
260 | && apt-get install -y -q --no-install-recommends \
261 | ca-certificates \
262 | wget \
263 | && apt-get clean \
264 | && rm -r /var/lib/apt/lists/*
265 |
266 | # Configure Nginx and apply fix for very long server names
267 | RUN echo "daemon off;" >> /etc/nginx/nginx.conf \
268 | && sed -i 's/^http {/&\n server_names_hash_bucket_size 128;/g' /etc/nginx/nginx.conf
269 |
270 | # Install Forego
271 | ADD https://github.com/jwilder/forego/releases/download/v0.16.1/forego /usr/local/bin/forego
272 | RUN chmod u+x /usr/local/bin/forego
273 |
274 | ENV DOCKER_GEN_VERSION 0.7.3
275 |
276 | RUN wget https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \
277 | && tar -C /usr/local/bin -xvzf docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \
278 | && rm /docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz
279 |
280 | COPY . /app/
281 | WORKDIR /app/
282 |
283 | ENV DOCKER_HOST unix:///tmp/docker.sock
284 |
285 | VOLUME ["/etc/nginx/certs"]
286 |
287 | ENTRYPOINT ["/app/docker-entrypoint.sh"]
288 | CMD ["forego", "start", "-r"]
289 | ```
290 |
--------------------------------------------------------------------------------
/Tests/Find-DockerImage.Tests.ps1:
--------------------------------------------------------------------------------
1 | if (-not $ENV:BHProjectPath) {
2 | Set-BuildEnvironment -Path $PSScriptRoot\..
3 | }
4 |
5 | $FunctionName = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name).Replace('.Tests', '')
6 |
7 | Import-Module -Name (Join-Path $ENV:BHProjectPath $ENV:BHProjectName) -ErrorAction Stop
8 |
9 | Describe "$FunctionName" {
10 | InModuleScope $ENV:BHProjectName {
11 |
12 | . (Join-Path $ENV:BHProjectPath '.\Tests\Invoke-DockerHubWebRequest.Mock.ps1')
13 |
14 |
15 | # Wildcard
16 |
17 | It 'Use wildcard "*" if invoked w/o "SearchTerm" parameter' {
18 | $Result = Find-DockerImage
19 |
20 | $Result | Should -Not -BeNullOrEmpty
21 | }
22 |
23 |
24 | # Wildcard + SortBy
25 |
26 | It 'Use wildcard "*" if invoked w/o "SearchTerm" parameter and with "-SortBy Downloads"' {
27 | $Result = Find-DockerImage -SortBy Downloads
28 |
29 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
30 | }
31 |
32 | It 'Use wildcard "*" if invoked w/o "SearchTerm" parameter and with "-SortBy Stars"' {
33 | $Result = Find-DockerImage -SortBy Stars
34 |
35 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
36 | }
37 |
38 |
39 | # Wildcard + SortBy + Official/Automated
40 |
41 | It 'Use wildcard "*" if invoked w/o "SearchTerm" parameter and with "-SortBy Downloads -Automated"' {
42 | $Result = Find-DockerImage -SortBy Downloads -Automated
43 |
44 | $Result.Automated | Should -Not -Contain $false
45 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
46 | }
47 |
48 | It 'Use wildcard "*" if invoked w/o "SearchTerm" parameter and with "-SortBy Stars -Automated"' {
49 | $Result = Find-DockerImage -SortBy Stars -Automated
50 |
51 | $Result.Automated | Should -Not -Contain $false
52 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
53 | }
54 |
55 | It 'Use wildcard "*" if invoked w/o "SearchTerm" parameter and with "-SortBy Downloads -Official"' {
56 | $Result = Find-DockerImage -SortBy Downloads -Official
57 |
58 | $Result.Official | Should -Not -Contain $false
59 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
60 | }
61 |
62 | It 'Use wildcard "*" if invoked w/o "SearchTerm" parameter and with "-SortBy Stars -Official"' {
63 | $Result = Find-DockerImage -SortBy Stars -Official
64 |
65 | $Result.Official | Should -Not -Contain $false
66 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
67 | }
68 |
69 |
70 | # Pipeline: SearchTerm
71 |
72 | It 'Accept "SearchTerm" via Pipeline parameter' {
73 | $Result = 'automated' | Find-DockerImage
74 |
75 | $Result.Name -like '*automated*' | Should -HaveCount $Result.Count
76 | }
77 |
78 |
79 | # Pipeline: SearchTerm . Named: SortBy + Official/Automated
80 |
81 | It 'Accept "SearchTerm" via Pipeline parameter. Accept "-SortBy Downloads -Official" via Named parameters' {
82 | $Result = 'official' | Find-DockerImage -SortBy Downloads -Official
83 |
84 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
85 | $Result.Official | Should -Not -Contain $false
86 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
87 | }
88 |
89 | It 'Accept "SearchTerm" via Pipeline parameter. Accept "-SortBy Stars -Official" via Named parameters' {
90 | $Result = 'official' | Find-DockerImage -SortBy Stars -Official
91 |
92 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
93 | $Result.Official | Should -Not -Contain $false
94 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
95 | }
96 |
97 | It 'Accept "SearchTerm" via Pipeline parameter. Accept "-SortBy Downloads -Automated" via Named parameters' {
98 | $Result = 'automated' | Find-DockerImage -SortBy Downloads -Automated
99 |
100 | $Result.Name -like '*automated*' | Should -HaveCount $Result.Count
101 | $Result.Automated | Should -Not -Contain $false
102 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
103 | }
104 |
105 | It 'Accept "SearchTerm" via Pipeline parameter. Accept "-SortBy Stars -Automated" via Named parameters' {
106 | $Result = 'official' | Find-DockerImage -SortBy Stars -Official
107 |
108 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
109 | $Result.Official | Should -Not -Contain $false
110 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
111 | }
112 |
113 |
114 | # Named: SearchTerm
115 |
116 | It 'Accept "SearchTerm" via Pipeline parameter' {
117 | $Result = 'automated' | Find-DockerImage
118 |
119 | $Result.Name -like '*automated*' | Should -HaveCount $Result.Count
120 | }
121 |
122 |
123 | # Named: SearchTerm + SortBy
124 |
125 | It 'Accept "SearchTerm", "-SortBy Downloads" via Named parameters' {
126 | $Result = 'official' | Find-DockerImage -SortBy Downloads
127 |
128 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
129 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
130 | }
131 |
132 | It 'Accept "SearchTerm", "-SortBy Stars" via Named parameters' {
133 | $Result = 'official' | Find-DockerImage -SortBy Downloads
134 |
135 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
136 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
137 | }
138 |
139 |
140 | # Named: SearchTerm + SortBy + Official/Automated
141 |
142 | It 'Accept "SearchTerm", "-SortBy Downloads -Official" via Named parameters' {
143 | $Result = 'official' | Find-DockerImage -SortBy Downloads -Official
144 |
145 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
146 | $Result.Official | Should -Not -Contain $false
147 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
148 | }
149 |
150 | It 'Accept "SearchTerm", "-SortBy Stars -Official" via Named parameters' {
151 | $Result = 'official' | Find-DockerImage -SortBy Stars -Official
152 |
153 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
154 | $Result.Official | Should -Not -Contain $false
155 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
156 | }
157 |
158 | It 'Accept "SearchTerm", "-SortBy Downloads -Automated" via Named parameters' {
159 | $Result = 'automated' | Find-DockerImage -SortBy Downloads -Automated
160 |
161 | $Result.Name -like '*automated*' | Should -HaveCount $Result.Count
162 | $Result.Automated | Should -Not -Contain $false
163 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
164 | }
165 |
166 | It 'Accept "SearchTerm", "-SortBy Stars -Automated" via Named parameters' {
167 | $Result = 'official' | Find-DockerImage -SortBy Stars -Automated
168 |
169 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
170 | $Result.Automated | Should -Not -Contain $false
171 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
172 | }
173 |
174 |
175 |
176 |
177 |
178 | # Positional: SearchTerm
179 |
180 | It 'Accept "SearchTerm" via Positional parameter' {
181 | $Result = Find-DockerImage 'automated'
182 |
183 | $Result.Name -like '*automated*' | Should -HaveCount $Result.Count
184 | }
185 |
186 |
187 | # Positional: SearchTerm + SortBy
188 |
189 | It 'Accept "SearchTerm", "-SortBy Downloads" via Positional parameters' {
190 | $Result = Find-DockerImage 'official' 'Downloads'
191 |
192 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
193 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
194 | }
195 |
196 | It 'Accept "SearchTerm", "-SortBy Stars" via Positional parameters' {
197 | $Result = Find-DockerImage 'official' 'Stars'
198 |
199 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
200 | $Result[0].Stars | Should -BeGreaterThan $Result[-1].Stars
201 | }
202 |
203 |
204 | # Positional: SearchTerm + SortBy
205 |
206 | It 'Accept "SearchTerm", "-SortBy Downloads -Official" via Positional parameters' {
207 | $Result = Find-DockerImage -SortBy Downloads -Official
208 |
209 | $Result.Name -like '*official*' | Should -HaveCount $Result.Count
210 | $Result.Official | Should -Not -Contain $false
211 | $Result[0].Downloads | Should -BeGreaterThan $Result[-1].Downloads
212 | }
213 |
214 | }
215 | }
--------------------------------------------------------------------------------
/Tests/Invoke-DockerHubWebRequest.Mock.ps1:
--------------------------------------------------------------------------------
1 | function Invoke-DockerHubWebRequest {
2 | [CmdletBinding()]
3 | Param (
4 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
5 | [ValidateNotNullOrEmpty()]
6 | $Request,
7 |
8 | [Parameter(ValueFromRemainingArguments = $true)]
9 | $Dummy
10 | )
11 |
12 | Process {
13 | $Responce = '
14 | {
15 | "count":9,
16 | "next":"",
17 | "previous":"",
18 | "results":[
19 | {
20 | "repo_name":"official-1",
21 | "short_description":"Official image #1",
22 | "star_count":1,
23 | "pull_count":1,
24 | "repo_owner":"",
25 | "is_automated":false,
26 | "is_official":true
27 | },
28 | {
29 | "repo_name":"official-2",
30 | "short_description":"Official image #2",
31 | "star_count":2,
32 | "pull_count":2,
33 | "repo_owner":"",
34 | "is_automated":false,
35 | "is_official":true
36 | },
37 | {
38 | "repo_name":"official-3",
39 | "short_description":"Official image #3",
40 | "star_count":3,
41 | "pull_count":3,
42 | "repo_owner":"",
43 | "is_automated":true,
44 | "is_official":false
45 | },
46 | {
47 | "repo_name":"unofficial/not-automated",
48 | "short_description":"Unofficial & not automated image",
49 | "star_count":4,
50 | "pull_count":4,
51 | "repo_owner":"",
52 | "is_automated":false,
53 | "is_official":false
54 | },
55 | {
56 | "repo_name":"unofficial/automated",
57 | "short_description":"Unofficial & automated image",
58 | "star_count":5,
59 | "pull_count":5,
60 | "repo_owner":"",
61 | "is_automated":true,
62 | "is_official":false
63 | },
64 | {
65 | "repo_name":"unofficial/not-automated-stars",
66 | "short_description":"Unofficial & not automated [High stars count]",
67 | "star_count":666,
68 | "pull_count":6,
69 | "repo_owner":"",
70 | "is_automated":false,
71 | "is_official":false
72 | },
73 | {
74 | "repo_name":"unofficial/not-automated-downloads]",
75 | "short_description":"Unofficial & not automated [High downloads count]",
76 | "star_count":7,
77 | "pull_count":777,
78 | "repo_owner":"",
79 | "is_automated":false,
80 | "is_official":false
81 | },
82 | {
83 | "repo_name":"unofficial/automated-stars",
84 | "short_description":"Unofficial & automated [High stars count]",
85 | "star_count":888,
86 | "pull_count":8,
87 | "repo_owner":"",
88 | "is_automated":true,
89 | "is_official":false
90 | },
91 | {
92 | "repo_name":"unofficial/automated-downloads]",
93 | "short_description":"Unofficial & automated [High downloads count]",
94 | "star_count":9,
95 | "pull_count":999,
96 | "repo_owner":"",
97 | "is_automated":true,
98 | "is_official":false
99 | }
100 | ]
101 | }
102 | ' | ConvertFrom-Json
103 |
104 | switch -Wildcard ($Request) {
105 |
106 | '*is_automated=1*' {
107 | Write-Verbose 'Mocking: is_automated'
108 | $Responce.results = $Responce.results | Where-Object {$_.is_automated}
109 | }
110 |
111 | '*is_official=1*' {
112 | Write-Verbose 'Mocking: is_official'
113 | $Responce.results = $Responce.results | Where-Object {$_.is_official}
114 | }
115 |
116 | '*ordering=-pull_count' {
117 | Write-Verbose 'Mocking: pull_count'
118 | $Responce.results = $Responce.results | Sort-Object -Property 'pull_count' -Descending
119 | }
120 |
121 | '*ordering=-star_count*' {
122 | Write-Verbose 'Mocking: star_count'
123 | $Responce.results = $Responce.results | Sort-Object -Property 'star_count' -Descending
124 | }
125 |
126 | '*query=*' {
127 | if ($Request -match 'query=([^\*]\w+)') {
128 | Write-Verbose 'Mocking: query'
129 | $Responce.results = $Responce.results | Where-Object {$_.repo_name -like ('*{0}*' -f $Matches[1])}
130 | }
131 | }
132 | }
133 |
134 | $Responce.results
135 | }
136 | }
--------------------------------------------------------------------------------
/Tests/PSScriptAnalyzer.Tests.ps1:
--------------------------------------------------------------------------------
1 | if (-not $ENV:BHProjectPath) {
2 | Set-BuildEnvironment -Path $PSScriptRoot\..
3 | }
4 |
5 | $FunctionName = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name).Replace('.Tests', '')
6 |
7 | Describe "$FunctionName" {
8 | It 'Should not have any PSScriptAnalyzer warnings' {
9 | $ProjectRoot = $ENV:BHProjectPath
10 | $ModuleName = $ENV:BHProjectName
11 |
12 | $ScriptWarnings = @(
13 | Invoke-ScriptAnalyzer -Path "$ProjectRoot\$ModuleName" -Recurse -ExcludeRule 'PSUseToExportFieldsInManifest'
14 | )
15 |
16 | if ($ScriptWarnings) {
17 | $ScriptWarnings | Format-Table -AutoSize | Out-String | Write-Warning
18 | }
19 |
20 | $ScriptWarnings.Length | Should be 0
21 | }
22 | }
--------------------------------------------------------------------------------
/Tests/RunAllTests.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -Command "[Console]::SetBufferSize(1000, 3000) ; Import-Module -Name PSScriptAnalyzer, Pester, BuildHelpers ; Invoke-Pester -Path '%~dp0'"
3 | pause
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | # See http://www.appveyor.com/docs/appveyor-yml for many more options
2 |
3 | image: Visual Studio 2017
4 |
5 | #Publish to PowerShell Gallery with this key
6 | environment:
7 | NuGetApiKey:
8 | secure: NbIQ9vEo/6ZsKp4lA2FcYQYQ6BeNAkAtYbDLxQ8QJi2hIbaRVDf3DOrw5M9IMcyQ
9 |
10 | # Skip on updates to the readme.
11 | # We can force this by adding [skip ci] or [ci skip] anywhere in commit message
12 | skip_commits:
13 | message: /^(?=.*update)(?=.*readme).*$/
14 |
15 | build: off
16 |
17 | # Get latest GitVersion
18 | install:
19 | - choco install gitversion.portable --version 4.0.0 -y
20 |
21 | # Generate version
22 | before_test:
23 | - ps: '& (Join-Path $env:ChocolateyInstall "bin\GitVersion.exe") /l console /output buildserver'
24 |
25 | #Kick off the CI/CD pipeline
26 | test_script:
27 | - ps: . .\Build.ps1
--------------------------------------------------------------------------------