fig-lock 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c3ee68dd9533f30826adbc4476c751c7b2b2e94f
4
+ data.tar.gz: 5face655d47fc8a3bc173bcb08f73f3c1c6b656f
5
+ SHA512:
6
+ metadata.gz: cd3ff4c1df4b0535ef36c7fb356d1f7466d0f699fecf93de503abf252a60f3f9b76b7a93ab20147e247b9384e25e25734c753205be43fef92619119b5460bb04
7
+ data.tar.gz: 8f174825d487d3c781887e329f568f568f3a4f5c8599b702a855720cdf87c1124ac9b69f54972a6ec99f6201b153fcdd2e49c43b65240300ee1f91c941836174
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ coverage
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fig-lock.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # Fig::Lock
2
+
3
+ Generates fig.lock files based on fig.yml files.
4
+ Gets the latest versions of all images defined in a
5
+ fig.yml file, rewrites them to include the specific tags
6
+ of those versions, generates a fig.lock file.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'fig-lock'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install fig-lock
21
+
22
+ ## Usage
23
+
24
+ ### Install
25
+ The *install* command uses docker to retrieve all images
26
+ defined in fig.lock. If no fig.lock file exists, one will
27
+ be generated by invoking the *update* command.
28
+ ```
29
+ fig-lock install </path/to/fig.yml>
30
+ ```
31
+
32
+ ### Update
33
+ The *update* command uses docker to retrieve the latest versions
34
+ of all images defined in the fig.yml file and generates/updates
35
+ a corresponding fig.lock file in the same directory as the fig.yml file,
36
+ which uses specific version tags for these images.
37
+ ```
38
+ fig-lock update </path/to/fig.yml>
39
+ ```
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it ( http://github.com/<my-github-username>/fig-lock/fork )
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default=>:spec
data/bin/fig-lock ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.join(__dir__, '..', 'lib'))
3
+ require 'fig/lock/cli'
4
+
data/fig-lock.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fig/lock/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fig-lock"
8
+ spec.version = Fig::Lock::VERSION
9
+ spec.authors = ["Michael Shea"]
10
+ spec.email = ["michael.shea@salesforce.com"]
11
+ spec.summary = %q{Generates fig.lock files from fig.yml files}
12
+ spec.description = %q{Generates fig.lock files from fig.yml files}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "slop"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.5"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "simplecov"
27
+
28
+ end
data/lib/fig/lock.rb ADDED
@@ -0,0 +1,116 @@
1
+ require 'yaml'
2
+ require 'fig/lock/log'
3
+ require 'fig/lock/version'
4
+
5
+ module Fig
6
+ class Lock
7
+ class << self
8
+ def install(opts={})
9
+ Lock.new(opts).install
10
+ end
11
+
12
+ def update(opts={})
13
+ Lock.new(opts).update
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ module Fig
20
+ class Lock
21
+ include Fig::Lock::Log
22
+
23
+ attr_reader :lock_file, :file
24
+
25
+ def initialize(opts)
26
+ opts = merge_opts(opts)
27
+ @file = opts[:file]
28
+ @lock_file = lock_file_name(file)
29
+
30
+ fail "File #{file} does not exist" unless File.exists?(file)
31
+ fail "File #{file} is a directory" if File.directory?(file)
32
+ end
33
+
34
+ # Install images from a lock file on the local system
35
+ def install
36
+ if File.exists?(lock_file)
37
+ log.info "Lock file #{lock_file} found."
38
+ fetch_images(YAML.load(File.read(lock_file)))
39
+ else
40
+ log.info "No lock file found."
41
+ update
42
+ end
43
+ end
44
+
45
+ # Update an existing lock file, or create if none exists
46
+ def update
47
+ log.info "Generating lock file for #{file} ..."
48
+ hash = YAML.load(File.read(file))
49
+
50
+ fetch_images(hash)
51
+ select_latest(hash)
52
+
53
+ File.write(lock_file, hash.to_yaml)
54
+ end
55
+
56
+ private
57
+
58
+ # Construct the name of the lock file from the name of the fig file
59
+ def lock_file_name(file)
60
+ index = file.rindex('.')
61
+ raise "Input file #{file} has no file extension" unless index
62
+ file[0, index] << '.lock'
63
+ end
64
+
65
+ # Select the latest version for images in the fig hash. Updates the input hash.
66
+ def select_latest(hash)
67
+ log.info "Selecting latest tags:"
68
+ hash.each do |k,v|
69
+ image = v['image']
70
+ unless image.nil?
71
+ output = `sudo docker images #{image}`
72
+ fail "Unable to list image: #{image}.\n\tExit code:#{$?.exitstatus}\n\tOutput:#{output}" unless $?.exitstatus.zero?
73
+ tag = output.split("\n")[1].split(' ')[1]
74
+ tagged_image = "#{image}:#{tag}"
75
+ log.info "Resolved: #{tagged_image}"
76
+ v['image'] = tagged_image
77
+ end
78
+ end
79
+ end
80
+
81
+ # Fetch all images from the fig hash.
82
+ def fetch_images(hash)
83
+ log.info "Fetching images:"
84
+ hash.each do |k,v|
85
+ image = v['image']
86
+ if image
87
+ log.info "Fetching #{image} ..."
88
+ system "sudo docker pull #{image}"
89
+ fail "Unable to fetch image: #{image}.\n\tExit code:#{$?.exitstatus}" unless $?.exitstatus.zero?
90
+ end
91
+ end
92
+ log.info "Done fetching images."
93
+ end
94
+
95
+ def merge_opts(opts)
96
+ Defaults.opts.merge(opts).tap do |hash|
97
+ fail("file must be specified") unless hash[:file]
98
+ end
99
+ end
100
+ end
101
+
102
+ # Default values for parameters
103
+ class Defaults
104
+ class << self
105
+ def opts
106
+ {
107
+ file: file
108
+ }
109
+ end
110
+
111
+ def file
112
+ ENV.fetch 'FIG_FILE', File.join(__dir__, 'fig.yml')
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,42 @@
1
+ require 'slop'
2
+ require 'fig/lock'
3
+ require 'fig/lock/log'
4
+
5
+ def cmd_args(command, args)
6
+ if args.empty?
7
+ {}
8
+ elsif args.size == 1
9
+ {file: args[0]}
10
+ else
11
+ fail "Usage: fig-lock #{command} <file>"
12
+ end
13
+ end
14
+
15
+ # Execute a block.
16
+ def execute(&block)
17
+ run do |opts, args|
18
+ begin
19
+ yield(opts, args)
20
+ rescue StandardError => bang
21
+ if ENV['DEBUG']
22
+ Fig::Lock::Log.log.fatal bang
23
+ else
24
+ Fig::Lock::Log.log.fatal bang.message
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ opts = Slop.parse do
31
+ command 'install' do
32
+ execute do |opts, args|
33
+ Fig::Lock.install cmd_args('install', args)
34
+ end
35
+ end
36
+
37
+ command 'update' do
38
+ execute do |opts, args|
39
+ Fig::Lock.update cmd_args('update', args)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ require 'logger'
2
+ require 'fig/lock/version'
3
+
4
+ module Fig::Lock::Log
5
+ def log
6
+ Fig::Lock::Log.log
7
+ end
8
+ end
9
+
10
+ module Fig::Lock::Log
11
+ class << self
12
+ def log
13
+ @log ||= Logger.new(STDOUT).tap do |l|
14
+ l.level = Logger.const_get(ENV.fetch('LOG_LEVEL', 'INFO').upcase)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module Fig
2
+ class Lock
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,100 @@
1
+ $:.unshift(File.join(__dir__, '..', '..', 'lib'))
2
+
3
+ RSpec.configure do |config|
4
+ require 'simplecov'
5
+ SimpleCov.add_filter 'vendor'
6
+ SimpleCov.add_filter 'spec'
7
+ SimpleCov.start
8
+ end
9
+
10
+
11
+ require 'fig/lock'
12
+
13
+ module Fig
14
+
15
+ describe Lock do
16
+
17
+ before :each do
18
+ ENV['LOG_LEVEL'] = 'FATAL'
19
+ end
20
+
21
+ context 'class operations' do
22
+ it 'should install' do
23
+ expect(Lock).to receive(:new).with({}){
24
+ double('lock').tap do |lock|
25
+ expect(lock).to receive(:install)
26
+ end
27
+ }
28
+ Lock.install({})
29
+ end
30
+
31
+ it 'should update' do
32
+ expect(Lock).to receive(:new).with({}){
33
+ double('lock').tap do |lock|
34
+ expect(lock).to receive(:update)
35
+ end
36
+ }
37
+ Lock.update({})
38
+ end
39
+ end
40
+
41
+ context 'instance operations' do
42
+
43
+ before :each do
44
+ allow(File).to receive(:exists?).with('fig.yml'){true}
45
+ allow(File).to receive(:directory?).with('fig.yml'){false}
46
+ allow(File).to receive(:read).with('fig.yml'){yaml}
47
+ allow(File).to receive(:read).with('fig.lock'){yaml}
48
+ end
49
+
50
+ it 'should install' do
51
+ lock = Fig::Lock.new(registry: 'some.docker.com', file:'fig.yml')
52
+ allow(File).to receive(:exists?).with('fig.lock'){true}
53
+
54
+ expect(lock).to receive(:system).with('sudo docker pull some.docker.com/atlas/api'){true}
55
+
56
+ lock.install
57
+ end
58
+
59
+ it 'should update if no fig.lock exists' do
60
+ lock = Fig::Lock.new(registry: 'some.docker.com', file:'fig.yml')
61
+ allow(File).to receive(:exists?).with('fig.lock'){false}
62
+ expect(lock).to receive(:update)
63
+ lock.install
64
+ end
65
+
66
+ it 'should update' do
67
+ lock = Fig::Lock.new(registry: 'some.docker.com', file:'fig.yml')
68
+
69
+ expect(lock).to receive(:system).with('sudo docker pull some.docker.com/atlas/api'){true}
70
+ expect(lock).to receive(:`).with('sudo docker images some.docker.com/atlas/api'){docker_image_output}
71
+ expect(File).to receive(:write).with('fig.lock', expected_fig_lock)
72
+
73
+ lock.update
74
+ end
75
+
76
+ def expected_fig_lock
77
+ <<-eos
78
+ ---
79
+ web:
80
+ image: some.docker.com/atlas/api:20140611142604
81
+ eos
82
+ end
83
+
84
+ def docker_image_output
85
+ <<-eos
86
+ REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
87
+ some.docker.com/atlas/api 20140611142604 784dfb100eb0 4 hours ago 376.4 MB
88
+ eos
89
+ end
90
+
91
+ def yaml
92
+ <<-eos
93
+ ---
94
+ web:
95
+ image: some.docker.com/atlas/api
96
+ eos
97
+ end
98
+ end
99
+ end
100
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fig-lock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Shea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: slop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Generates fig.lock files from fig.yml files
84
+ email:
85
+ - michael.shea@salesforce.com
86
+ executables:
87
+ - fig-lock
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - .gitignore
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - bin/fig-lock
97
+ - fig-lock.gemspec
98
+ - lib/fig/lock.rb
99
+ - lib/fig/lock/cli.rb
100
+ - lib/fig/lock/log.rb
101
+ - lib/fig/lock/version.rb
102
+ - spec/fig/lock_spec.rb
103
+ homepage: ''
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.2.2
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Generates fig.lock files from fig.yml files
127
+ test_files:
128
+ - spec/fig/lock_spec.rb