docker-tags 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4baa52c3feb752ff98b2621f7f6eb9e10df82093
4
+ data.tar.gz: 08b3a7866cfe1dd611e3b056d805a951c47b5bba
5
+ SHA512:
6
+ metadata.gz: e68d86489751589dfac9ebdb71650e42eb5b608dbe77ee083bb478df5b458db1eaf2e339e378d2eaa6e458e10637e0e387dd2652ab7ae18b175d99748bda8b81
7
+ data.tar.gz: ca4c9c9499a975df3b854de9cb217a5d4284afa1a8e85e087cf94b313c8e9dbe6a8ab63d566ebedb6ad4b017a3688bba4183f095d3aaae04efed9e89386c48e0
@@ -0,0 +1,39 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/bundle
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ # Gemfile.lock
32
+ # .ruby-version
33
+ # .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
37
+
38
+ *~
39
+ *.db
@@ -0,0 +1 @@
1
+ inherit_from: .rubocop_todo.yml
@@ -0,0 +1,119 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2016-01-29 16:38:45 +0100 using RuboCop version 0.36.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: IgnoreEmptyBlocks.
12
+ Lint/UnusedBlockArgument:
13
+ Exclude:
14
+ - 'lib/dockertags/cli.rb'
15
+
16
+ # Offense count: 3
17
+ Metrics/AbcSize:
18
+ Max: 33
19
+
20
+ # Offense count: 12
21
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
22
+ # URISchemes: http, https
23
+ Metrics/LineLength:
24
+ Max: 122
25
+
26
+ # Offense count: 3
27
+ # Configuration parameters: CountComments.
28
+ Metrics/MethodLength:
29
+ Max: 25
30
+
31
+ # Offense count: 1
32
+ # Configuration parameters: CountComments.
33
+ Metrics/ModuleLength:
34
+ Max: 112
35
+
36
+ # Offense count: 1
37
+ Style/AccessorMethodName:
38
+ Exclude:
39
+ - 'lib/dockertags/commands.rb'
40
+
41
+ # Offense count: 1
42
+ # Cop supports --auto-correct.
43
+ Style/AlignArray:
44
+ Exclude:
45
+ - 'docker-tags.gemspec'
46
+
47
+ # Offense count: 2
48
+ Style/ClassVars:
49
+ Exclude:
50
+ - 'lib/dockertags.rb'
51
+
52
+ # Offense count: 2
53
+ # Cop supports --auto-correct.
54
+ # Configuration parameters: SingleLineConditionsOnly.
55
+ Style/ConditionalAssignment:
56
+ Exclude:
57
+ - 'lib/dockertags/commands.rb'
58
+
59
+ # Offense count: 6
60
+ Style/Documentation:
61
+ Exclude:
62
+ - 'spec/**/*'
63
+ - 'test/**/*'
64
+ - 'lib/dockertags.rb'
65
+ - 'lib/dockertags/cli.rb'
66
+ - 'lib/dockertags/commands.rb'
67
+ - 'lib/dockertags/db.rb'
68
+ - 'lib/dockertags/log.rb'
69
+ - 'lib/dockertags/utils.rb'
70
+
71
+ # Offense count: 2
72
+ # Cop supports --auto-correct.
73
+ # Configuration parameters: MaxLineLength.
74
+ Style/IfUnlessModifier:
75
+ Exclude:
76
+ - 'lib/dockertags.rb'
77
+ - 'lib/dockertags/commands.rb'
78
+
79
+ # Offense count: 3
80
+ # Cop supports --auto-correct.
81
+ Style/MutableConstant:
82
+ Exclude:
83
+ - 'lib/dockertags/db.rb'
84
+ - 'lib/dockertags/version.rb'
85
+
86
+ # Offense count: 1
87
+ # Cop supports --auto-correct.
88
+ # Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
89
+ # SupportedStyles: skip_modifier_ifs, always
90
+ Style/Next:
91
+ Exclude:
92
+ - 'lib/dockertags/commands.rb'
93
+
94
+ # Offense count: 2
95
+ # Cop supports --auto-correct.
96
+ Style/RedundantBegin:
97
+ Exclude:
98
+ - 'lib/dockertags/db.rb'
99
+
100
+ # Offense count: 1
101
+ # Cop supports --auto-correct.
102
+ # Configuration parameters: AllowAsExpressionSeparator.
103
+ Style/Semicolon:
104
+ Exclude:
105
+ - 'lib/dockertags/commands.rb'
106
+
107
+ # Offense count: 1
108
+ # Cop supports --auto-correct.
109
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
110
+ # SupportedStyles: space, no_space
111
+ Style/SpaceBeforeBlockBraces:
112
+ Enabled: false
113
+
114
+ # Offense count: 3
115
+ # Cop supports --auto-correct.
116
+ # Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
117
+ # SupportedStyles: single_quotes, double_quotes
118
+ Style/StringLiterals:
119
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Gem dependencies
4
+ gemspec
5
+
6
+ # Development dependencies
7
+ gem 'rake'
8
+ gem 'rubocop', require: false
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dockertags (0.0.1)
5
+ commander (~> 4.3)
6
+ faraday
7
+ sqlite3
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ast (2.2.0)
13
+ commander (4.3.5)
14
+ highline (~> 1.7.2)
15
+ faraday (0.9.2)
16
+ multipart-post (>= 1.2, < 3)
17
+ highline (1.7.8)
18
+ multipart-post (2.0.0)
19
+ parser (2.3.0.2)
20
+ ast (~> 2.2)
21
+ powerpack (0.1.1)
22
+ rainbow (2.1.0)
23
+ rake (10.4.2)
24
+ rubocop (0.36.0)
25
+ parser (>= 2.3.0.0, < 3.0)
26
+ powerpack (~> 0.1)
27
+ rainbow (>= 1.99.1, < 3.0)
28
+ ruby-progressbar (~> 1.7)
29
+ ruby-progressbar (1.7.5)
30
+ sqlite3 (1.3.10)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ bundler (~> 1.3)
37
+ dockertags!
38
+ rake
39
+ rubocop
40
+
41
+ BUNDLED WITH
42
+ 1.10.6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,100 @@
1
+ # docker-tags
2
+
3
+ Track latest tags for Docker images.
4
+
5
+ ## Installation
6
+
7
+ Run from a git clone:
8
+
9
+ ```
10
+ git clone https://github.com/jasperla/docker-tags
11
+ bundle install --path vendor/bundle
12
+ ```
13
+
14
+ or install the gem:
15
+
16
+ ```
17
+ gem install docker-tags
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ All the commands for `docker-tags` take a `--db /path/to/db`
23
+ argument to select the SQLite database. Bu default
24
+ `$PWD/docker-tags.db` is used.
25
+
26
+ ### Initialize the database
27
+
28
+ This creates an empty database and creates the needed tables:
29
+
30
+ ```
31
+ docker-tags initdb
32
+ ```
33
+
34
+ ### Follow and unfollow an image
35
+
36
+ In order to start tracking the tags for an image, we have to start
37
+ following it:
38
+
39
+ ```
40
+ docker-tags follow jasperla/docker-go-cross
41
+ ```
42
+
43
+ In order to stop tracking, run the same command but with `unfollow`.
44
+
45
+ ### Show latest tag
46
+
47
+ ```
48
+ docker-tags latest jasperla/docker-go-cross
49
+ ```
50
+
51
+ This will return a JSON hash for this particular image:
52
+
53
+ ```
54
+ {
55
+ "jasperla/docker-go-cross": {
56
+ "image": "jasperla/docker-go-cross",
57
+ "layer": "c2c017e1",
58
+ "tag": "latest"
59
+ }
60
+ }
61
+ ```
62
+
63
+ In this case there is only one tag, `latest` (which is otherwise
64
+ filtered). If we follow more images, we can run `latest` without any
65
+ arguments and the latest tags for all images will be displayed.
66
+
67
+ ### Report
68
+
69
+ To generate a report based on the new tags that were pushed to the
70
+ Docker Hub since the last time `latest` or `report` were ran:
71
+
72
+ ```
73
+ docker-tags report jasperla/docker-go-cross
74
+ ```
75
+
76
+ Just like `latest`, `report` will also work without any arguments.
77
+
78
+ ### Dump all known tags
79
+
80
+ Essentially a SQL to JSON conversion of the database:
81
+
82
+ ```
83
+ docker-tags dump
84
+ ```
85
+
86
+ ## ToDo
87
+
88
+ - tests and docs (oh the irony)
89
+
90
+ ## Copyright and license
91
+
92
+ MIT, please see the LICENSE file.
93
+
94
+ ## Contributing
95
+
96
+ 1. Fork it
97
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
98
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
99
+ 4. Push to the branch (`git push origin my-new-feature`)
100
+ 5. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ desc "Open an irb session preloaded with this API"
5
+ task :console do
6
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
7
+ require 'dockertags'
8
+ require 'irb'
9
+ ARGV.clear
10
+ IRB.start
11
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'dockertags'
5
+ rescue
6
+ dockertags_path = File.expand_path('../../lib', __FILE__)
7
+ $LOAD_PATH.unshift(dockertags_path)
8
+
9
+ require 'dockertags'
10
+ end
11
+
12
+ Commander::Runner.instance.run!
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
+ require 'dockertags/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'docker-tags'
6
+ s.version = DockerTags::VERSION
7
+ s.authors = ['Jasper Lievisse Adriaanse'],
8
+ s.email = ['jasper@humppa.nl']
9
+ s.homepage = "https://github.com/jasperla/docker-tags"
10
+ s.summary = 'Track tags of Docker images.'
11
+ s.description = 'Track and report tags of followed Docker images.'
12
+
13
+ s.required_ruby_version = '>= 1.9.3'
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ s.require_paths = ['lib']
18
+
19
+ s.add_runtime_dependency 'commander', '~> 4.3'
20
+ s.add_runtime_dependency 'faraday'
21
+ s.add_runtime_dependency 'sqlite3'
22
+
23
+ s.add_development_dependency 'bundler', '~> 1.3'
24
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
2
+ # See LICENSE for details
3
+
4
+ require 'dockertags/version'
5
+ require 'dockertags/log'
6
+ require 'dockertags/db'
7
+ require 'dockertags/utils'
8
+ require 'dockertags/cli'
9
+ require 'dockertags/commands'
10
+
11
+ module DockerTags
12
+ unless defined? @@database_path
13
+ @@database_path = 'docker-tags.db'
14
+ end
15
+
16
+ def self.database_path
17
+ @@database_path
18
+ end
19
+
20
+ def self.database_path=(path)
21
+ @@database_path = path
22
+ end
23
+ end
@@ -0,0 +1,106 @@
1
+ # Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
2
+ # See LICENSE for details
3
+
4
+ require 'commander/import'
5
+
6
+ module DockerTags
7
+ class Cli
8
+ program :name, 'Docker Tags'
9
+ program :version, DockerTags::VERSION
10
+ program :description, 'Stay notified of new image tags'
11
+
12
+ default_command :report
13
+
14
+ command :report do |c|
15
+ c.syntax = 'docker-tag-notify report [options]'
16
+ c.description = 'Report of any new tags, correlating layers'
17
+ c.option '--image NAME', String, 'Name of image to follow'
18
+ c.option '--db /path/to/dtn.db', String, 'path to database'
19
+ c.action do |args, options|
20
+ options.default image: args[0]
21
+ options.default db: DockerTags.database_path
22
+
23
+ DockerTags.database_path = options.db
24
+
25
+ DockerTags::Log.warn("Ignoring arguments #{args[1..-1]}") if args.length > 1
26
+ DockerTags::Commands.report(options.image)
27
+ end
28
+ end
29
+
30
+ command :latest do |c|
31
+ c.syntax = 'docker-tag-notify latest [options]'
32
+ c.description = 'Get the "latest" tag/aliases'
33
+ c.option '--image NAME', String, 'Name of image to follow'
34
+ c.option '--db /path/to/dtn.db', String, 'path to database'
35
+ c.action do |args, options|
36
+ options.default image: args[0]
37
+ options.default db: DockerTags.database_path
38
+
39
+ DockerTags.database_path = options.db
40
+
41
+ DockerTags::Log.warn("Ignoring arguments #{args[1..-1]}") if args.length > 1
42
+ DockerTags::Commands.latest(options.image)
43
+ end
44
+ end
45
+
46
+ command :follow do |c|
47
+ c.syntax = 'docker-tag-notify follow <image>'
48
+ c.description = 'Track a new image and add current known tags to the db'
49
+ c.option '--image NAME', String, 'Name of image to follow'
50
+ c.option '--db /path/to/dtn.db', String, 'path to database'
51
+ c.action do |args, options|
52
+ options.default image: args[0]
53
+ options.default db: DockerTags.database_path
54
+
55
+ DockerTags.database_path = options.db
56
+
57
+ DockerTags::Log.warn("Ignoring arguments #{args[1..-1]}") if args.length > 1
58
+ DockerTags::Log.err("Invalid image name: '#{options.image}'") unless DockerTags::Utils.valid_image?(options.image)
59
+ DockerTags::Commands.follow(options.image)
60
+ end
61
+ end
62
+
63
+ command :unfollow do |c|
64
+ c.syntax = 'docker-tag-notify unfollow <image>'
65
+ c.description = 'Stop tracking an image and purge it from the db'
66
+ c.option '--image NAME', String, 'Name of image to stop following'
67
+ c.option '--db /path/to/dtn.db', String, 'path to database'
68
+ c.action do |args, options|
69
+ options.default image: args[0]
70
+ options.default db: DockerTags.database_path
71
+
72
+ DockerTags.database_path = options.db
73
+
74
+ DockerTags::Log.warn("Ignoring arguments #{args[1..-1]}") if args.length > 1
75
+ DockerTags::Log.err("Invalid image name: '#{options.image}'") unless DockerTags::Utils.valid_image?(options.image)
76
+ DockerTags::Commands.unfollow(options.image)
77
+ end
78
+ end
79
+
80
+ command :initdb do |c|
81
+ c.syntax = 'docker-tag-notify init [options]'
82
+ c.description = 'Setup and initialize the database'
83
+ c.option '--db /path/to/dtn.db', String, 'path to database'
84
+ c.action do |args, options|
85
+ options.default db: DockerTags.database_path
86
+
87
+ DockerTags.database_path = options.db
88
+
89
+ DockerTags::Commands.initdb
90
+ end
91
+ end
92
+
93
+ command :dump do |c|
94
+ c.syntax = 'docker-tag-notify dump [options]'
95
+ c.description = 'Print the full database contents'
96
+ c.option '--db /path/to/dtn.db', String, 'path to database'
97
+ c.action do |_, options|
98
+ options.default db: DockerTags.database_path
99
+
100
+ DockerTags.database_path = options.db
101
+
102
+ DockerTags::Commands.dump
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,173 @@
1
+ # Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
2
+ # See LICENSE for details
3
+
4
+ require 'faraday'
5
+ require 'json'
6
+
7
+ module DockerTags
8
+ module Commands
9
+ def self.follow(image)
10
+ dbh = DockerTags::Db.new
11
+
12
+ # There can only be one.
13
+ r = dbh.query "SELECT name FROM images WHERE name = '#{image}'"
14
+ if r.size > 0
15
+ DockerTags::Log.err("Already following image '#{image}'")
16
+ end
17
+
18
+ dbh.query "INSERT INTO images VALUES('#{image}', '')"
19
+ dbh.close
20
+ end
21
+
22
+ def self.unfollow(image)
23
+ dbh = DockerTags::Db.new
24
+ dbh.query "DELETE FROM images WHERE name = '#{image}'"
25
+ dbh.query "DELETE FROM tags WHERE image = '#{image}'"
26
+
27
+ n = dbh.changes
28
+ puts "Succesfully removed #{n - 1} tags for #{image}" if n > 0
29
+ dbh.close
30
+ end
31
+
32
+ def self.initdb
33
+ dbh = DockerTags::Db.new
34
+
35
+ dbh.query DockerTags::Db::CREATE_IMAGES_TABLE
36
+ dbh.query DockerTags::Db::CREATE_TAGS_TABLE
37
+
38
+ dbh.close
39
+ end
40
+
41
+ def self.dump
42
+ dbh = DockerTags::Db.new
43
+
44
+ data = {}
45
+ data[:images] = dbh.query 'SELECT * FROM images'
46
+ data[:tags] = dbh.query 'SELECT * FROM tags'
47
+
48
+ puts JSON.pretty_generate(data)
49
+ dbh.close
50
+ end
51
+
52
+ def self.get_images
53
+ dbh = DockerTags::Db.new false
54
+
55
+ r = dbh.query('SELECT name FROM images')
56
+
57
+ images = []
58
+ r.each { |i| images << i[0] }
59
+ dbh.close
60
+
61
+ images
62
+ end
63
+
64
+ def self.report(image)
65
+ if image.nil? || image == ''
66
+ images = get_images
67
+ else
68
+ images = [image]
69
+ end
70
+
71
+ result = {}
72
+ images.each do |i|
73
+ new_tags = sync_tags(i)
74
+ if new_tags.size > 0
75
+ r = { image => { tags: [] } }
76
+ new_tags.each do |t|
77
+ r[image][:tags] << {
78
+ tag: t['name'],
79
+ layer: t['layer']
80
+ }
81
+ end
82
+
83
+ result[i] = r
84
+ end
85
+ end
86
+
87
+ puts JSON.pretty_generate(result)
88
+ end
89
+
90
+ def self.latest(image)
91
+ if image.nil? || image == ''
92
+ image_names = get_images
93
+ else
94
+ image_names = [image]
95
+ end
96
+
97
+ latest_images = {}
98
+ image_names.each do |i|
99
+ sync_tags(i)
100
+
101
+ dbh = DockerTags::Db.new
102
+ rows = dbh.query "SELECT latest FROM images WHERE name = '#{i}'"
103
+ latest_layer = rows[0]['latest']
104
+
105
+ rows = dbh.query "SELECT tag, layer FROM tags WHERE layer = '#{latest_layer}' AND tag != 'latest'"
106
+ dbh.close
107
+
108
+ image_result = {
109
+ image: i,
110
+ layer: latest_layer,
111
+ tag: []
112
+ }
113
+
114
+ # Image only has the 'latest' tag, do display it in that case.
115
+ if rows.empty?
116
+ image_result[:tag] = 'latest'
117
+ else
118
+ rows.each { |t| image_result[:tag] << t['tag'] }
119
+ end
120
+
121
+ latest_images[i] = image_result
122
+ end
123
+
124
+ puts JSON.pretty_generate(latest_images)
125
+ end
126
+
127
+ def self.sync_tags(image)
128
+ conn = Faraday.new(url: 'https://registry.hub.docker.com/v1') do |faraday|
129
+ faraday.request :url_encoded
130
+ faraday.adapter Faraday.default_adapter
131
+ end
132
+
133
+ resp = conn.get "repositories/#{image}/tags"
134
+ status = resp.status
135
+
136
+ if status == 404
137
+ DockerTags::Log.err("Could not find image '#{image}' on Docker Hub")
138
+ elsif status != 200
139
+ DockerTags::Log.err("Could not retrieve tags for '#{image}' (error: #{status})")
140
+ end
141
+
142
+ all_tags = JSON.parse(resp.body)
143
+
144
+ dbh = DockerTags::Db.new
145
+
146
+ # Now get all the existing tags for this image
147
+ current_tags = dbh.query "SELECT tag AS name, layer AS layer FROM tags WHERE image = '#{image}'"
148
+
149
+ # prune the results
150
+ current_tags.each { |t| t.delete(0); t.delete(1) }
151
+
152
+ # Compare the existing tags with what we've just fetched.
153
+ # Save the result of the difference and return that later.
154
+ new_tags = all_tags - current_tags
155
+
156
+ # Finish by inserting the list of new tags.
157
+ new_tags.each do |t|
158
+ dbh.query "INSERT INTO tags VALUES('#{t['name']}','#{t['layer']}','#{image}')"
159
+ end
160
+
161
+ latest = all_tags.select { |t| t['name'] == 'latest' }
162
+ if latest.size > 0
163
+ # Set the latest layer
164
+ dbh.query "UPDATE images SET latest = '#{latest[0]['layer']}' WHERE name = '#{image}'"
165
+ end
166
+
167
+ dbh.close
168
+
169
+ # Return the hash of differences for #report to handle
170
+ new_tags
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
2
+ # See LICENSE for details
3
+
4
+ require 'sqlite3'
5
+
6
+ module DockerTags
7
+ class Db
8
+ CREATE_IMAGES_TABLE = %{
9
+ CREATE TABLE IF NOT EXISTS images (
10
+ name varchar(30),
11
+ latest varchar(16)
12
+ );
13
+ }
14
+
15
+ CREATE_TAGS_TABLE = %{
16
+ CREATE TABLE IF NOT EXISTS tags (
17
+ tag varchar(30),
18
+ layer varchar(8),
19
+ image varchar(16)
20
+ );
21
+ }
22
+
23
+ def initialize(as_hash = true)
24
+ begin
25
+ @dbh = SQLite3::Database.new DockerTags.database_path
26
+ @dbh.results_as_hash = as_hash
27
+ rescue SQLite3::Exception => e
28
+ DockerTags::Log.sql_err(e, __method__)
29
+ end
30
+ end
31
+
32
+ def query(query)
33
+ begin
34
+ @dbh.execute(query)
35
+ rescue SQLite3::Exception => e
36
+ DockerTags::Log.sql_err(e, __method__)
37
+ end
38
+ end
39
+
40
+ def close
41
+ @dbh.close if @dbh
42
+ end
43
+
44
+ def changes
45
+ @dbh.changes
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ # Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
2
+ # See LICENSE for details
3
+
4
+ module DockerTags
5
+ module Log
6
+ def self.warn(str)
7
+ puts "WARN: #{str}"
8
+ end
9
+
10
+ def self.err(str)
11
+ puts "ERROR: #{str}"
12
+ exit
13
+ end
14
+
15
+ def self.sql_err(e, m)
16
+ puts "An SQLite error occured in #{m}: #{e}"
17
+ exit
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ # Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
2
+ # See LICENSE for details
3
+
4
+ module DockerTags
5
+ module Utils
6
+ # basic image name validation. cannot be empty of contain spaces
7
+ def self.valid_image?(name)
8
+ if name.nil? || name.empty? || (name.length != name.sub(/\s*/, "").length)
9
+ nil
10
+ else
11
+ true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ # Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>
2
+ # See LICENSE for details
3
+
4
+ module DockerTags
5
+ VERSION = '0.1.0'
6
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: docker-tags
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jasper Lievisse Adriaanse
8
+ - jasper@humppa.nl
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-01-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: commander
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '4.3'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '4.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: faraday
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: sqlite3
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: bundler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.3'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
70
+ description: Track and report tags of followed Docker images.
71
+ email:
72
+ - jasper@humppa.nl
73
+ executables:
74
+ - docker-tags
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".rubocop.yml"
80
+ - ".rubocop_todo.yml"
81
+ - Gemfile
82
+ - Gemfile.lock
83
+ - LICENSE
84
+ - README.md
85
+ - Rakefile
86
+ - bin/docker-tags
87
+ - docker-tags.gemspec
88
+ - lib/dockertags.rb
89
+ - lib/dockertags/cli.rb
90
+ - lib/dockertags/commands.rb
91
+ - lib/dockertags/db.rb
92
+ - lib/dockertags/log.rb
93
+ - lib/dockertags/utils.rb
94
+ - lib/dockertags/version.rb
95
+ homepage: https://github.com/jasperla/docker-tags
96
+ licenses: []
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 1.9.3
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.4.5.1
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Track tags of Docker images.
118
+ test_files: []