tagfish 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/tagfish +2 -22
- data/lib/tagfish/api_call.rb +21 -35
- data/lib/tagfish/api_error.rb +4 -0
- data/lib/tagfish/api_response.rb +25 -0
- data/lib/tagfish/cli/base_command.rb +13 -0
- data/lib/tagfish/cli/main_command.rb +31 -0
- data/lib/tagfish/cli/tags_command.rb +41 -0
- data/lib/tagfish/{update → cli}/update_command.rb +9 -4
- data/lib/tagfish/docker_http_auth.rb +6 -6
- data/lib/tagfish/docker_registry_v1_client.rb +7 -7
- data/lib/tagfish/docker_registry_v2_client.rb +11 -11
- data/lib/tagfish/docker_registry_vboth_client.rb +5 -6
- data/lib/tagfish/docker_uri.rb +5 -3
- data/lib/tagfish/version.rb +1 -1
- metadata +8 -11
- data/.gitignore +0 -14
- data/Dockerfile +0 -24
- data/Gemfile +0 -4
- data/README.md +0 -157
- data/Rakefile +0 -39
- data/lib/tagfish/tags_command.rb +0 -35
- data/logo.png +0 -0
- data/tagfish.gemspec +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5ff081cce0c22b7b5f8a8139045485d3fa2184d
|
4
|
+
data.tar.gz: 9d316b76e1972b0544bcce06eda7cbe4112f3020
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7770cdc629f1c9adcd61b2f7b5ce20a3669396b8972841af905ee9ae28dbcd430bc1931b3642fe5cd70b306ea37720032ed3e5a08bbd2b5b49f3058003ab9e5
|
7
|
+
data.tar.gz: 2348139104553d2376420aeebd7b8a9d5eab001a0e3d623ea89cfa1862791d3e80b50304ea45cc31c9f77cabc8f4b25b7322e917320870e97a27711c23885c48
|
data/bin/tagfish
CHANGED
@@ -2,26 +2,6 @@
|
|
2
2
|
|
3
3
|
$LOAD_PATH << File.expand_path("../../lib", __FILE__)
|
4
4
|
|
5
|
-
require '
|
6
|
-
require 'tagfish/tags_command'
|
7
|
-
require 'tagfish/update/update_command'
|
8
|
-
require 'tagfish/version'
|
5
|
+
require 'tagfish/cli/main_command'
|
9
6
|
|
10
|
-
|
11
|
-
class MainCommand < Clamp::Command
|
12
|
-
option ["-v", "--version"], :flag, "display version" do
|
13
|
-
puts "tagfish-#{Tagfish::VERSION}"
|
14
|
-
exit 0
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class MainCommand < Clamp::Command
|
19
|
-
subcommand "tags", "find tags for a repository", TagsCommand
|
20
|
-
end
|
21
|
-
|
22
|
-
class MainCommand < Clamp::Command
|
23
|
-
subcommand "update", "inspect files for outdated dependencies", Update::UpdateCommand
|
24
|
-
end
|
25
|
-
|
26
|
-
MainCommand.run
|
27
|
-
end
|
7
|
+
Tagfish::CLI::MainCommand.run
|
data/lib/tagfish/api_call.rb
CHANGED
@@ -1,59 +1,45 @@
|
|
1
1
|
require 'tagfish/docker_http_auth'
|
2
|
+
require 'tagfish/api_error'
|
3
|
+
require 'tagfish/api_response'
|
2
4
|
|
3
5
|
module Tagfish
|
4
6
|
class APICall
|
7
|
+
|
5
8
|
attr_accessor :uri
|
6
9
|
attr_accessor :http
|
7
10
|
attr_accessor :request
|
8
11
|
attr_accessor :http_auth
|
9
|
-
|
10
|
-
|
12
|
+
attr_accessor :debug
|
13
|
+
|
14
|
+
def initialize (debug = false)
|
15
|
+
@debug = debug
|
11
16
|
@auth = nil
|
12
17
|
end
|
13
|
-
|
18
|
+
|
14
19
|
def get(uri_string)
|
15
20
|
@uri = URI.parse(uri_string)
|
16
21
|
@http = Net::HTTP.new(uri.host, uri.port)
|
17
22
|
@http.use_ssl = true if uri.port == 443
|
23
|
+
@http.set_debug_output($stderr) if debug
|
18
24
|
@request = Net::HTTP::Get.new(uri.request_uri)
|
19
25
|
if http_auth
|
20
26
|
@request.basic_auth(http_auth.username, http_auth.password)
|
21
27
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def auth(registry)
|
26
|
-
@http_auth = DockerHttpAuth.new(registry)
|
27
|
-
end
|
28
|
-
|
29
|
-
def json
|
30
|
-
begin
|
31
|
-
response = http.request(request)
|
32
|
-
if response.code == "200"
|
33
|
-
return JSON.parse(response.body)
|
34
|
-
else
|
35
|
-
abort("Call to the registry API failed, the following resource might not exist:\n#{uri.to_s}")
|
36
|
-
end
|
37
|
-
rescue SocketError
|
38
|
-
puts "ERROR: SocketError"
|
39
|
-
end
|
28
|
+
http_response = http.request(request)
|
29
|
+
APIResponse.new(http_response)
|
40
30
|
end
|
41
31
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
abort("Call to the registry API failed, the following resource might not exist:\n#{uri.to_s}")
|
32
|
+
def get!(uri_string)
|
33
|
+
response = get(uri_string)
|
34
|
+
if response.code != 200
|
35
|
+
raise APIError, "call to '#{uri_string}' failed with #{response.code}"
|
47
36
|
end
|
37
|
+
response
|
48
38
|
end
|
49
|
-
|
50
|
-
def
|
51
|
-
|
52
|
-
response = http.request(request)
|
53
|
-
return response.fetch("Docker-Content-Digest")
|
54
|
-
rescue SocketError
|
55
|
-
puts "ERROR: SocketError"
|
56
|
-
end
|
39
|
+
|
40
|
+
def auth(registry)
|
41
|
+
@http_auth = DockerHttpAuth.for_registry(registry)
|
57
42
|
end
|
43
|
+
|
58
44
|
end
|
59
|
-
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Tagfish
|
2
|
+
|
3
|
+
class APIResponse
|
4
|
+
|
5
|
+
def initialize(http_response)
|
6
|
+
@http_response = http_response
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :http_response
|
10
|
+
|
11
|
+
def json
|
12
|
+
JSON.parse(http_response.body)
|
13
|
+
end
|
14
|
+
|
15
|
+
def code
|
16
|
+
Integer(http_response.code)
|
17
|
+
end
|
18
|
+
|
19
|
+
def digest
|
20
|
+
http_response.fetch("Docker-Content-Digest")
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'tagfish/cli/base_command'
|
2
|
+
require 'tagfish/cli/tags_command'
|
3
|
+
require 'tagfish/cli/update_command'
|
4
|
+
require 'tagfish/version'
|
5
|
+
|
6
|
+
module Tagfish
|
7
|
+
module CLI
|
8
|
+
|
9
|
+
class MainCommand < BaseCommand
|
10
|
+
|
11
|
+
option ["-v", "--version"], :flag, "display version" do
|
12
|
+
puts "tagfish-#{Tagfish::VERSION}"
|
13
|
+
exit 0
|
14
|
+
end
|
15
|
+
|
16
|
+
subcommand "tags", "find tags for a repository", TagsCommand
|
17
|
+
|
18
|
+
subcommand "update", "inspect files for outdated dependencies", UpdateCommand
|
19
|
+
|
20
|
+
def run(*args)
|
21
|
+
super(*args)
|
22
|
+
rescue Tagfish::APIError => e
|
23
|
+
signal_error e.message
|
24
|
+
rescue SocketError => e
|
25
|
+
signal_error e.message
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'tagfish/cli/base_command'
|
2
|
+
require "tagfish/docker_uri"
|
3
|
+
require "tagfish/docker_registry_client"
|
4
|
+
|
5
|
+
module Tagfish
|
6
|
+
module CLI
|
7
|
+
|
8
|
+
class TagsCommand < BaseCommand
|
9
|
+
|
10
|
+
parameter "REPOSITORY", "docker repository"
|
11
|
+
option ["-l", "--latest"], :flag, "only return latest explicitly tagged image"
|
12
|
+
option ["-s", "--short"], :flag, "only return tag, not full image path"
|
13
|
+
|
14
|
+
def execute
|
15
|
+
|
16
|
+
docker_uri = DockerURI.parse(repository)
|
17
|
+
docker_api = DockerRegistryClient.for(docker_uri, debug?)
|
18
|
+
|
19
|
+
if latest?
|
20
|
+
tags = docker_api.tags
|
21
|
+
latest_tags = tags.latest_tags
|
22
|
+
if latest_tags.empty?
|
23
|
+
signal_error "No image explicitly tagged in this Repository, " +
|
24
|
+
"only `latest` tag available."
|
25
|
+
end
|
26
|
+
tags_found = latest_tags
|
27
|
+
|
28
|
+
else
|
29
|
+
tags_found = docker_api.tag_names
|
30
|
+
end
|
31
|
+
|
32
|
+
tags_fqdn = tags_found.map do |tag_name|
|
33
|
+
short? ? tag_name : docker_uri.with_tag(tag_name).to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
puts tags_fqdn
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -1,11 +1,16 @@
|
|
1
|
+
require 'tagfish/cli/base_command'
|
1
2
|
require 'tagfish/update/updater'
|
2
3
|
require 'tagfish/update/differ'
|
3
4
|
require 'tagfish/update/uri_filters'
|
4
5
|
require 'tagfish/tokeniser'
|
5
6
|
|
6
7
|
module Tagfish
|
7
|
-
module
|
8
|
-
|
8
|
+
module CLI
|
9
|
+
|
10
|
+
class UpdateCommand < BaseCommand
|
11
|
+
|
12
|
+
include Tagfish::Update
|
13
|
+
|
9
14
|
parameter "[FILE]", "file to update", :default => "Dockerfile"
|
10
15
|
option ["-d", "--dry-run"], :flag, "enable dry run"
|
11
16
|
option "--only", "PATTERN", "Only update repositories matching pattern. Wildcards (*) may be used."
|
@@ -21,8 +26,8 @@ module Tagfish
|
|
21
26
|
updated = Tokeniser.dump(updater.update(Tokeniser.tokenise(original)))
|
22
27
|
|
23
28
|
puts Differ.diff(original, updated)
|
24
|
-
|
25
|
-
if not dry_run?
|
29
|
+
|
30
|
+
if not dry_run?
|
26
31
|
File.write(file, updated)
|
27
32
|
end
|
28
33
|
end
|
@@ -2,12 +2,12 @@ require 'json'
|
|
2
2
|
require 'base64'
|
3
3
|
|
4
4
|
module Tagfish
|
5
|
-
class DockerHttpAuth
|
6
5
|
|
7
|
-
|
8
|
-
attr_accessor :password
|
6
|
+
module DockerHttpAuth
|
9
7
|
|
10
|
-
|
8
|
+
Credentials = Struct.new(:username, :password)
|
9
|
+
|
10
|
+
def self.for_registry(registry)
|
11
11
|
file_path = '~/.docker/config.json'
|
12
12
|
|
13
13
|
begin
|
@@ -19,11 +19,11 @@ module Tagfish
|
|
19
19
|
json_config = JSON.parse(config.read())
|
20
20
|
config.close()
|
21
21
|
if json_config['auths'].length == 0
|
22
|
-
|
22
|
+
Credentials.new(nil, nil)
|
23
23
|
else
|
24
24
|
b64_auth = json_config['auths'][registry]['auth']
|
25
25
|
auth = Base64.decode64(b64_auth)
|
26
|
-
|
26
|
+
Credentials.new(*auth.split(':'))
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -2,11 +2,11 @@ require 'tagfish/docker_registry_vboth_client'
|
|
2
2
|
|
3
3
|
module Tagfish
|
4
4
|
class DockerRegistryV1Client < DockerRegistryVbothClient
|
5
|
-
|
5
|
+
|
6
6
|
def api_version
|
7
7
|
'v1'
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def tag_names
|
11
11
|
tags.tag_names
|
12
12
|
end
|
@@ -15,13 +15,13 @@ module Tagfish
|
|
15
15
|
tags_list = tags_api(tags_json)
|
16
16
|
Tagfish::Tags.new(tags_list)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
private
|
20
20
|
|
21
21
|
def tags_json
|
22
|
-
api_call.get(tags_uri).json
|
22
|
+
api_call.get!(tags_uri).json
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def tags_api(api_response_data)
|
26
26
|
case api_response_data
|
27
27
|
when Hash
|
@@ -34,11 +34,11 @@ module Tagfish
|
|
34
34
|
raise "unexpected type #{api_response_data.class}"
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def ping_uri
|
39
39
|
"#{base_uri}/v1/_ping"
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def tags_uri
|
43
43
|
"#{base_uri}/v1/repositories/#{docker_uri.repository}/tags"
|
44
44
|
end
|
@@ -2,11 +2,11 @@ require 'tagfish/docker_registry_vboth_client'
|
|
2
2
|
|
3
3
|
module Tagfish
|
4
4
|
class DockerRegistryV2Client < DockerRegistryVbothClient
|
5
|
-
|
5
|
+
|
6
6
|
def api_version
|
7
7
|
'v2'
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def tag_names
|
11
11
|
tags_json["tags"]
|
12
12
|
end
|
@@ -16,34 +16,34 @@ module Tagfish
|
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
|
-
|
19
|
+
|
20
20
|
def tags_json
|
21
|
-
api_call.get(tags_uri).json
|
21
|
+
api_call.get!(tags_uri).json
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def hash(tag)
|
25
|
-
api_call.get(hash_uri(tag)).json
|
25
|
+
api_call.get!(hash_uri(tag)).json
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def tags_list
|
29
29
|
if tag_names.nil?
|
30
30
|
abort("No Tags found for this repository")
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
tags_with_hashes = tag_names.inject({}) do |dict, tag|
|
34
34
|
dict[tag] = hash(tag)["fsLayers"]
|
35
35
|
dict
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def ping_uri
|
40
40
|
"#{base_uri}/v2/"
|
41
41
|
end
|
42
42
|
|
43
43
|
def tags_uri
|
44
|
-
"#{base_uri}/v2/#{docker_uri.repository}/tags/list"
|
44
|
+
"#{base_uri}/v2/#{docker_uri.repository}/tags/list"
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def hash_uri(tag)
|
48
48
|
"#{base_uri}/v2/#{docker_uri.repository}/manifests/#{tag}"
|
49
49
|
end
|
@@ -8,16 +8,15 @@ module Tagfish
|
|
8
8
|
class DockerRegistryVbothClient
|
9
9
|
|
10
10
|
attr_accessor :docker_uri
|
11
|
-
attr_accessor :http_auth
|
12
11
|
attr_accessor :api_call
|
13
12
|
|
14
|
-
def initialize(docker_uri)
|
15
|
-
@api_call = APICall.new
|
13
|
+
def initialize(docker_uri, debug)
|
14
|
+
@api_call = APICall.new(debug)
|
16
15
|
@docker_uri = docker_uri
|
17
|
-
code = api_call.get(ping_uri).
|
16
|
+
code = api_call.get(ping_uri).code
|
18
17
|
if code == 401
|
19
18
|
api_call.auth(docker_uri.registry)
|
20
|
-
code = api_call.get(ping_uri).
|
19
|
+
code = api_call.get(ping_uri).code
|
21
20
|
end
|
22
21
|
if code == 401
|
23
22
|
raise DockerRegistryClient::AuthenticationError, "Please `docker login <REGISTRY>` and try again"
|
@@ -25,7 +24,7 @@ module Tagfish
|
|
25
24
|
raise DockerRegistryClient::APIVersionError, "Not recognized"
|
26
25
|
end
|
27
26
|
end
|
28
|
-
|
27
|
+
|
29
28
|
def base_uri
|
30
29
|
"#{docker_uri.protocol}#{docker_uri.registry}"
|
31
30
|
end
|
data/lib/tagfish/docker_uri.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'tagfish/docker_http_auth'
|
2
|
-
|
3
1
|
module Tagfish
|
2
|
+
|
4
3
|
class DockerURI
|
4
|
+
|
5
5
|
URI_PARSER = %r{
|
6
6
|
(https?:\/\/)? # Optional protocol
|
7
7
|
(?:([\w.\-]+\.[\w.\-]+)\/)? # Optional registry
|
@@ -33,7 +33,7 @@ module Tagfish
|
|
33
33
|
@protocol = "https://"
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def repo_and_tag
|
38
38
|
tag.nil? ? "#{repository}" : "#{repository}:#{tag}"
|
39
39
|
end
|
@@ -59,5 +59,7 @@ module Tagfish
|
|
59
59
|
"#{registry}#{reg_sep}#{repository}#{tag_sep}#{tag}"
|
60
60
|
end
|
61
61
|
end
|
62
|
+
|
62
63
|
end
|
64
|
+
|
63
65
|
end
|
data/lib/tagfish/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tagfish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clement Labbe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -102,14 +102,15 @@ executables:
|
|
102
102
|
extensions: []
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
|
-
- ".gitignore"
|
106
|
-
- Dockerfile
|
107
|
-
- Gemfile
|
108
|
-
- README.md
|
109
|
-
- Rakefile
|
110
105
|
- bin/tagfish
|
111
106
|
- lib/tagfish.rb
|
112
107
|
- lib/tagfish/api_call.rb
|
108
|
+
- lib/tagfish/api_error.rb
|
109
|
+
- lib/tagfish/api_response.rb
|
110
|
+
- lib/tagfish/cli/base_command.rb
|
111
|
+
- lib/tagfish/cli/main_command.rb
|
112
|
+
- lib/tagfish/cli/tags_command.rb
|
113
|
+
- lib/tagfish/cli/update_command.rb
|
113
114
|
- lib/tagfish/docker_http_auth.rb
|
114
115
|
- lib/tagfish/docker_registry_client.rb
|
115
116
|
- lib/tagfish/docker_registry_v1_client.rb
|
@@ -117,15 +118,11 @@ files:
|
|
117
118
|
- lib/tagfish/docker_registry_vboth_client.rb
|
118
119
|
- lib/tagfish/docker_uri.rb
|
119
120
|
- lib/tagfish/tags.rb
|
120
|
-
- lib/tagfish/tags_command.rb
|
121
121
|
- lib/tagfish/tokeniser.rb
|
122
122
|
- lib/tagfish/update/differ.rb
|
123
|
-
- lib/tagfish/update/update_command.rb
|
124
123
|
- lib/tagfish/update/updater.rb
|
125
124
|
- lib/tagfish/update/uri_filters.rb
|
126
125
|
- lib/tagfish/version.rb
|
127
|
-
- logo.png
|
128
|
-
- tagfish.gemspec
|
129
126
|
homepage: https://github.com/realestate-com-au/tagfish
|
130
127
|
licenses:
|
131
128
|
- MIT
|
data/.gitignore
DELETED
data/Dockerfile
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
FROM alpine:3.3
|
2
|
-
MAINTAINER Clement Labbe <clement.labbe@rea-group.com>
|
3
|
-
|
4
|
-
RUN apk add --update ruby \
|
5
|
-
ruby-dev \
|
6
|
-
ruby-io-console \
|
7
|
-
diffutils \
|
8
|
-
linux-headers \
|
9
|
-
build-base \
|
10
|
-
ca-certificates && \
|
11
|
-
rm /var/cache/apk/* && \
|
12
|
-
rm -rf /usr/share/ri
|
13
|
-
|
14
|
-
RUN echo -e 'gem: --no-rdoc --no-ri' > /etc/gemrc && \
|
15
|
-
gem update --system && \
|
16
|
-
gem install bundler && \
|
17
|
-
rm -rf /usr/share/ri
|
18
|
-
|
19
|
-
COPY pkg/tagfish-latest.gem /cwd/
|
20
|
-
WORKDIR /cwd
|
21
|
-
RUN gem install tagfish-latest.gem
|
22
|
-
RUN mkdir -p /root/.docker
|
23
|
-
|
24
|
-
ENTRYPOINT ["tagfish"]
|
data/Gemfile
DELETED
data/README.md
DELETED
@@ -1,157 +0,0 @@
|
|
1
|
-
# Tagfish
|
2
|
-
|
3
|
-

|
4
|
-
|
5
|
-
Tagfish is a CLI tool to interact with Docker registries.
|
6
|
-
|
7
|
-
Features include:
|
8
|
-
|
9
|
-
- List all the tags of a given Docker repository
|
10
|
-
- Return the most recent explicit tag of a repository
|
11
|
-
- Update a file with the newest tags
|
12
|
-
- Authenticate by reading native Docker config file
|
13
|
-
- Works against hub.docker.com and private registries
|
14
|
-
- Supports Docker Registry/Distribution API v1 and v2
|
15
|
-
|
16
|
-
To use Tagfish against a registry requiring authentication, you first need to authenticate to the given registry using `docker login <REGISTRY>`.
|
17
|
-
|
18
|
-
## Table of contents
|
19
|
-
|
20
|
-
<!-- MarkdownTOC autolink=true bracket=round depth=4 -->
|
21
|
-
|
22
|
-
- [Usage](#usage)
|
23
|
-
- [`tagfish tags`](#tagfish-tags)
|
24
|
-
- [Example](#example)
|
25
|
-
- [`tagfish update`](#tagfish-update)
|
26
|
-
- [Example](#example-2)
|
27
|
-
- [Official repositories](#official-repositories)
|
28
|
-
- [Installation](#installation)
|
29
|
-
- [Gem](#gem)
|
30
|
-
- [Limitations](#limitations)
|
31
|
-
- [Docker image](#docker-image)
|
32
|
-
- [Contributing](#contributing)
|
33
|
-
- [Licence](#licence)
|
34
|
-
|
35
|
-
|
36
|
-
<!-- /MarkdownTOC -->
|
37
|
-
|
38
|
-
## Usage
|
39
|
-
The Tagfish CLI tool has different subcommands for interacting with Docker registries.
|
40
|
-
|
41
|
-
### `tagfish tags`
|
42
|
-
The `tags` subcommands is used to retrieve tags from a given repository:
|
43
|
-
|
44
|
-
Usage:
|
45
|
-
tagfish tags [OPTIONS] REPOSITORY
|
46
|
-
|
47
|
-
Parameters:
|
48
|
-
REPOSITORY docker repository
|
49
|
-
|
50
|
-
Options:
|
51
|
-
-l, --latest only return latest explicitly tagged image
|
52
|
-
-s, --short only return tag, not full image path
|
53
|
-
-d, --digest returns the tag's digest (v2 API only)
|
54
|
-
-h, --help print help
|
55
|
-
|
56
|
-
Where `repository` is a docker repository path, including the docker registry. The tags are returned in alphabetical order.
|
57
|
-
|
58
|
-
The `--latest` option gets the image ID of the docker image tagged `latest` in the repository, finds a matching image with a tag set manually (e.g: date, version number), and returns that tag. This option will not work if there is no image tagged `latest` in your repository.
|
59
|
-
|
60
|
-
EXPERIMENTAL: The `--digest` option returns the tag with its hash. It only works in conjunction
|
61
|
-
with the `--latest` option and against a registry running the v2 API. As of today it doesn't work against Docker Hub, because we're accessing it over API v1 to avoid the authentication mecanism. It returns a string such as:
|
62
|
-
```
|
63
|
-
my-registry/cowbell/tagfish:1.1.3@sha256:491c87df7d5f...
|
64
|
-
```
|
65
|
-
This is used to lock down not only to a specific tag version, but to a specific image hash. So even if the tag is reassigned later, this will still point to the same image.
|
66
|
-
|
67
|
-
#### Example
|
68
|
-
```
|
69
|
-
$ tagfish tags alpine
|
70
|
-
alpine:2.6
|
71
|
-
alpine:2.7
|
72
|
-
alpine:3.1
|
73
|
-
alpine:3.2
|
74
|
-
alpine:edge
|
75
|
-
alpine:latest
|
76
|
-
```
|
77
|
-
|
78
|
-
### `tagfish update`
|
79
|
-
The `update` subcommand is used to update a file with the latest tags available:
|
80
|
-
|
81
|
-
Usage:
|
82
|
-
tagfish update [OPTIONS] FILE
|
83
|
-
|
84
|
-
Parameters:
|
85
|
-
FILE file to update
|
86
|
-
|
87
|
-
Options:
|
88
|
-
-d, --dry-run enable dry run
|
89
|
-
--only PATTERN Only update repositories matching pattern. Wildcards `*` may be used.
|
90
|
-
-h, --help print help
|
91
|
-
|
92
|
-
#### Example
|
93
|
-
```
|
94
|
-
$ tagfish update --dry-run Dockerfile
|
95
|
-
-FROM docker-registry.delivery.realestate.com.au/gpde/ubuntu-ruby2.2:201508191500
|
96
|
-
+FROM docker-registry.delivery.realestate.com.au/gpde/ubuntu-ruby2.2:201511261833
|
97
|
-
```
|
98
|
-
|
99
|
-
#### Official repositories
|
100
|
-
`tagfish update` will update repositories such as:
|
101
|
-
```
|
102
|
-
private.registry/namespace/repository:tag
|
103
|
-
namespace/repository:tag
|
104
|
-
```
|
105
|
-
However, it will not update the tag of official repositories, such as:
|
106
|
-
```
|
107
|
-
ubuntu:tag
|
108
|
-
```
|
109
|
-
This is because updating to a new OS automatically might be something you want to avoid, and because it is hard to match a repository without a namespace.
|
110
|
-
|
111
|
-
## Installation
|
112
|
-
### Gem
|
113
|
-
Tagfish is packaged as a Ruby gem. Install it from the command line:
|
114
|
-
|
115
|
-
```
|
116
|
-
$ gem install tagfish
|
117
|
-
```
|
118
|
-
|
119
|
-
#### Limitations
|
120
|
-
Tagfish requires Ruby 2.2 or newer if the registry you are accessing restricts TLS to v1.2.
|
121
|
-
|
122
|
-
### Docker image
|
123
|
-
Tagfish is released as a Docker image as well, and can be run with:
|
124
|
-
|
125
|
-
```
|
126
|
-
docker run --rm \
|
127
|
-
-v ~/.docker:/root/.docker:ro \
|
128
|
-
-v ${PWD}:/cwd \
|
129
|
-
cowbell/tagfish \
|
130
|
-
<COMMAND>
|
131
|
-
```
|
132
|
-
|
133
|
-
## Contributing
|
134
|
-
|
135
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/realestate-com-au/tagfish .
|
136
|
-
|
137
|
-
## Licence
|
138
|
-
|
139
|
-
Copyright (c) 2015 REA Group Ltd.
|
140
|
-
|
141
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
142
|
-
of this software and associated documentation files (the "Software"), to deal
|
143
|
-
in the Software without restriction, including without limitation the rights
|
144
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
145
|
-
copies of the Software, and to permit persons to whom the Software is
|
146
|
-
furnished to do so, subject to the following conditions:
|
147
|
-
|
148
|
-
The above copyright notice and this permission notice shall be included in
|
149
|
-
all copies or substantial portions of the Software.
|
150
|
-
|
151
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
152
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
153
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
154
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
155
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
156
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
157
|
-
THE SOFTWARE.
|
data/Rakefile
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require "fileutils"
|
3
|
-
|
4
|
-
spec = Gem::Specification::load(Dir.glob("*.gemspec").first)
|
5
|
-
gem_file = "pkg/#{spec.name}-#{spec.version}.gem"
|
6
|
-
docker_uri = "cowbell/#{spec.name}"
|
7
|
-
tag = "#{spec.version}"
|
8
|
-
|
9
|
-
desc "build docker image locally"
|
10
|
-
task build_docker_image: [:build] do
|
11
|
-
FileUtils.copy(gem_file, "pkg/tagfish-latest.gem")
|
12
|
-
sh "docker build -t #{docker_uri}:#{tag} ."
|
13
|
-
sh "docker tag -f #{docker_uri}:#{tag} #{docker_uri}:latest"
|
14
|
-
puts "Built image #{docker_uri}"
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "Release docker image"
|
18
|
-
task release_docker_image: [:build_docker_image] do
|
19
|
-
sh "docker push #{docker_uri}:#{tag}"
|
20
|
-
sh "docker push #{docker_uri}:latest"
|
21
|
-
end
|
22
|
-
|
23
|
-
desc "Check for git sync"
|
24
|
-
task :no_local_changes do
|
25
|
-
sh "git pull"
|
26
|
-
sh "git diff HEAD --exit-code"
|
27
|
-
end
|
28
|
-
|
29
|
-
desc "Tag version into git repo"
|
30
|
-
task git_tag: [:no_local_changes] do
|
31
|
-
puts "blah"
|
32
|
-
sh "git tag #{tag}"
|
33
|
-
sh "git push origin --tags"
|
34
|
-
end
|
35
|
-
|
36
|
-
desc "Release gem and docker image"
|
37
|
-
task release_all: [:git_tag, :release, :release_docker_image] do
|
38
|
-
puts "Released all"
|
39
|
-
end
|
data/lib/tagfish/tags_command.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require "tagfish/docker_uri"
|
2
|
-
require "tagfish/docker_registry_client"
|
3
|
-
|
4
|
-
module Tagfish
|
5
|
-
class TagsCommand < Clamp::Command
|
6
|
-
parameter "REPOSITORY", "docker repository"
|
7
|
-
option ["-l", "--latest"], :flag, "only return latest explicitly tagged image"
|
8
|
-
option ["-s", "--short"], :flag, "only return tag, not full image path"
|
9
|
-
|
10
|
-
def execute
|
11
|
-
|
12
|
-
docker_uri = DockerURI.parse(repository)
|
13
|
-
docker_api = DockerRegistryClient.for(docker_uri)
|
14
|
-
|
15
|
-
if latest?
|
16
|
-
tags = docker_api.tags
|
17
|
-
latest_tags = tags.latest_tags
|
18
|
-
if latest_tags.empty?
|
19
|
-
signal_error "No image explicitly tagged in this Repository, " +
|
20
|
-
"only `latest` tag available."
|
21
|
-
end
|
22
|
-
tags_found = latest_tags
|
23
|
-
|
24
|
-
else
|
25
|
-
tags_found = docker_api.tag_names
|
26
|
-
end
|
27
|
-
|
28
|
-
tags_fqdn = tags_found.map do |tag_name|
|
29
|
-
short? ? tag_name : docker_uri.with_tag(tag_name).to_s
|
30
|
-
end
|
31
|
-
|
32
|
-
puts tags_fqdn
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/logo.png
DELETED
Binary file
|
data/tagfish.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'tagfish/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "tagfish"
|
8
|
-
spec.version = Tagfish::VERSION
|
9
|
-
spec.authors = ["Clement Labbe"]
|
10
|
-
spec.email = ["clement.labbe@rea-group.com"]
|
11
|
-
spec.summary = %q{Command line utility for docker registries}
|
12
|
-
spec.description = "Retrieve repository tags, update dockerfiles, and more!"
|
13
|
-
spec.homepage = "https://github.com/realestate-com-au/tagfish"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
-
spec.bindir = "bin"
|
18
|
-
spec.executables = ["tagfish"]
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.10"
|
22
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
-
spec.add_development_dependency "rspec", "~> 3.3.0"
|
24
|
-
spec.add_dependency "clamp", "~> 1.0.0"
|
25
|
-
spec.add_dependency "diffy", "~> 3.0.0"
|
26
|
-
spec.add_dependency "json", "~> 1.8.0"
|
27
|
-
end
|