dockly 0.0.2
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 +7 -0
- data/.cane +3 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +221 -0
- data/Rakefile +19 -0
- data/bin/dockly +8 -0
- data/dockly.gemspec +31 -0
- data/lib/dockly.rb +44 -0
- data/lib/dockly/aws.rb +60 -0
- data/lib/dockly/build_cache.rb +131 -0
- data/lib/dockly/cli.rb +46 -0
- data/lib/dockly/deb.rb +141 -0
- data/lib/dockly/docker.rb +169 -0
- data/lib/dockly/foreman.rb +37 -0
- data/lib/dockly/rake_task.rb +40 -0
- data/lib/dockly/util/git.rb +13 -0
- data/lib/dockly/util/tar.rb +27 -0
- data/lib/dockly/version.rb +3 -0
- data/lib/foreman/cli_fix.rb +9 -0
- data/lib/foreman/export/base_fix.rb +6 -0
- data/spec/dockly/aws_spec.rb +17 -0
- data/spec/dockly/build_cache_spec.rb +144 -0
- data/spec/dockly/deb_spec.rb +238 -0
- data/spec/dockly/docker_spec.rb +216 -0
- data/spec/dockly/foreman_spec.rb +39 -0
- data/spec/dockly_spec.rb +1 -0
- data/spec/fixtures/Procfile +1 -0
- data/spec/fixtures/Rakefile +17 -0
- data/spec/fixtures/not_a_tar-2.txt +1 -0
- data/spec/fixtures/not_a_tar.txt +1 -0
- data/spec/fixtures/tar-2.tar +0 -0
- data/spec/fixtures/test-1.tar +0 -0
- data/spec/fixtures/test-2.tar.gz +0 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/vcr.rb +11 -0
- metadata +297 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
class Dockly::Foreman
|
2
|
+
include Dockly::Util::DSL
|
3
|
+
include Dockly::Util::Logger::Mixin
|
4
|
+
|
5
|
+
logger_prefix '[dockly foreman]'
|
6
|
+
dsl_attribute :name, :env, :procfile, :type, :user, :root_dir, :init_dir,
|
7
|
+
:log_dir, :build_dir, :prefix
|
8
|
+
|
9
|
+
default_value :build_dir, 'build/foreman'
|
10
|
+
default_value :env, ""
|
11
|
+
default_value :procfile, './Procfile'
|
12
|
+
default_value :type, 'upstart'
|
13
|
+
default_value :user, 'nobody'
|
14
|
+
default_value :root_dir, "/tmp"
|
15
|
+
default_value :init_dir, "/etc/init"
|
16
|
+
default_value :log_dir, '/var/log'
|
17
|
+
|
18
|
+
def create!
|
19
|
+
ensure_present! :name, :init_dir, :build_dir, :procfile, :type, :user
|
20
|
+
|
21
|
+
info "cleaning build dir"
|
22
|
+
FileUtils.rm_rf(build_dir)
|
23
|
+
FileUtils.mkdir_p(build_dir)
|
24
|
+
cli = ::Foreman::CLI.new
|
25
|
+
cli.options = {
|
26
|
+
:root => root_dir,
|
27
|
+
:env => env,
|
28
|
+
:procfile => procfile,
|
29
|
+
:app => name,
|
30
|
+
:log => log_dir,
|
31
|
+
:prefix => prefix,
|
32
|
+
:user => user,
|
33
|
+
}
|
34
|
+
info "exporting"
|
35
|
+
cli.export(type, build_dir)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'dockly'
|
3
|
+
|
4
|
+
$rake_task_logger = Dockly::Util::Logger.new('[dockly rake_task]', STDOUT, false)
|
5
|
+
|
6
|
+
if File.exist?('dockly.rb')
|
7
|
+
Dockly.setup
|
8
|
+
end
|
9
|
+
|
10
|
+
class Rake::DebTask < Rake::Task
|
11
|
+
def needed?
|
12
|
+
raise "Package does not exist" if package.nil?
|
13
|
+
!package.exists?
|
14
|
+
end
|
15
|
+
|
16
|
+
def package
|
17
|
+
Dockly::Deb[name.split(':').last.to_sym]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Rake::DSL
|
22
|
+
def deb(*args, &block)
|
23
|
+
Rake::DebTask.define_task(*args, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
namespace :dockly do
|
28
|
+
task :load do
|
29
|
+
raise "No dockly.rb found!" unless File.exist?('dockly.rb')
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace :deb do
|
33
|
+
Dockly::Deb.instances.values.each do |inst|
|
34
|
+
deb inst.name => 'dockly:load' do |name|
|
35
|
+
Thread.current[:rake_task] = name
|
36
|
+
inst.build
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'grit'
|
2
|
+
|
3
|
+
module Dockly::Util::Git
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def git_repo
|
7
|
+
@git_repo ||= Grit::Repo.new('.')
|
8
|
+
end
|
9
|
+
|
10
|
+
def git_sha
|
11
|
+
@git_sha ||= git_repo.git.show.lines.first.chomp.match(/^commit ([a-f0-9]+)$/)[1][0..6] rescue 'unknown'
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Dockly::Util::Tar
|
2
|
+
extend self
|
3
|
+
|
4
|
+
def is_tar?(path)
|
5
|
+
if File.size(path) < 262
|
6
|
+
return false
|
7
|
+
end
|
8
|
+
magic = nil
|
9
|
+
File.open(path, "r") do |f|
|
10
|
+
f.read(257)
|
11
|
+
magic = f.read(5)
|
12
|
+
end
|
13
|
+
magic == "ustar"
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_gzip?(path)
|
17
|
+
if File.size(path) < 2
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
magic = nil
|
21
|
+
File.open(path, "r") do |f|
|
22
|
+
magic = f.read(2)
|
23
|
+
end
|
24
|
+
magic = magic.unpack('H*')[0]
|
25
|
+
magic == "1f8b"
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockly::AWS do
|
4
|
+
subject { Dockly::AWS }
|
5
|
+
|
6
|
+
describe '#reset_cache!' do
|
7
|
+
before do
|
8
|
+
subject.instance_variable_set(:@s3, double)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'sets @s3 to nil' do
|
12
|
+
expect { subject.reset_cache! }
|
13
|
+
.to change { subject.instance_variable_get(:@s3) }
|
14
|
+
.to(nil)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockly::BuildCache, :docker do
|
4
|
+
subject { described_class.new(:name => :test_build_cache) }
|
5
|
+
let(:image) { ::Docker::Image.build('from base') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
subject.s3_bucket 'lol'
|
9
|
+
subject.s3_object_prefix 'swag'
|
10
|
+
subject.image = image
|
11
|
+
subject.hash_command 'md6' # haters come at me
|
12
|
+
subject.build_command 'touch lol'
|
13
|
+
subject.output_dir '/'
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#execute!' do
|
17
|
+
before do
|
18
|
+
subject.stub(:up_to_date?).and_return(up_to_date)
|
19
|
+
subject.stub(:push_cache)
|
20
|
+
subject.stub(:push_to_s3)
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when the object is up to date' do
|
24
|
+
let(:up_to_date) { true }
|
25
|
+
|
26
|
+
it "does not have the file lol" do
|
27
|
+
i = subject.execute!
|
28
|
+
output = ""
|
29
|
+
puts i
|
30
|
+
i.run('ls').start.attach { |chunk| output += chunk }
|
31
|
+
output.should_not include('lol')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when the object is not up to date' do
|
36
|
+
let(:up_to_date) { false }
|
37
|
+
|
38
|
+
it "does have the file lol" do
|
39
|
+
i = subject.execute!
|
40
|
+
output = ""
|
41
|
+
i.run('ls').attach { |chunk| output += chunk }
|
42
|
+
output.should include('lol')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#run_build" do
|
48
|
+
before do
|
49
|
+
subject.stub(:push_to_s3)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "does have the file lol" do
|
53
|
+
i = subject.execute!
|
54
|
+
output = ""
|
55
|
+
i.run('ls').attach { |chunk| output += chunk }
|
56
|
+
output.should include('lol')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#pull_from_s3' do
|
61
|
+
let (:file) { subject.pull_from_s3('hey') }
|
62
|
+
let (:object) { double(:object) }
|
63
|
+
|
64
|
+
before do
|
65
|
+
subject.connection.stub(:get_object).and_return object
|
66
|
+
object.stub(:body).and_return 'hey dad'
|
67
|
+
end
|
68
|
+
|
69
|
+
after do
|
70
|
+
path = file.path
|
71
|
+
file.close
|
72
|
+
File.delete(path)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns a File with the data pulled' do
|
76
|
+
file.read.should == 'hey dad'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#up_to_date?' do
|
81
|
+
context 'when the object exists in s3' do
|
82
|
+
before { subject.connection.stub(:head_object) }
|
83
|
+
|
84
|
+
its(:up_to_date?) { should be_true }
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when the object does not exist in s3' do
|
88
|
+
before do
|
89
|
+
subject.connection.stub(:head_object)
|
90
|
+
.and_raise(Excon::Errors::NotFound.new('help'))
|
91
|
+
end
|
92
|
+
|
93
|
+
its(:up_to_date?) { should be_false }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '#hash_output' do
|
98
|
+
let(:output) {
|
99
|
+
"682aa2a07693cc27756eee9751db3903 /etc/vim/vimrc"
|
100
|
+
}
|
101
|
+
|
102
|
+
before do
|
103
|
+
subject.image = image
|
104
|
+
subject.hash_command 'md5sum /etc/vim/vimrc'
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'returns the output of the hash_command in the container' do
|
108
|
+
subject.hash_output.should == output
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#copy_output_dir' do
|
113
|
+
let(:container) { Docker::Container.create('Image' => 'base', 'Cmd' => %w[true]) }
|
114
|
+
let(:file) { subject.copy_output_dir(container) }
|
115
|
+
let(:hash) { 'this_really_unique_hash' }
|
116
|
+
let(:path) { file.path }
|
117
|
+
|
118
|
+
before do
|
119
|
+
subject.stub(:hash_output).and_return(hash)
|
120
|
+
subject.output_dir '/root/'; container.wait
|
121
|
+
end
|
122
|
+
after do
|
123
|
+
file.close
|
124
|
+
File.delete(path)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'returns a File of the specified directory from the Container' do
|
128
|
+
expect(file.path).to include("#{hash}")
|
129
|
+
file.should be_a File
|
130
|
+
file.read.should include('root/.bashrc')
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe '#s3_object' do
|
135
|
+
before do
|
136
|
+
subject.stub(:s3_object_prefix) { 'lol' }
|
137
|
+
subject.stub(:hash_output) { 'lel' }
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'returns the s3_prefix merged with the hash_output' do
|
141
|
+
subject.s3_object(subject.hash_output).should == 'lollel'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe Dockly::Deb do
|
5
|
+
describe '#create_package!' do
|
6
|
+
subject do
|
7
|
+
Dockly::Deb.new do
|
8
|
+
package_name 'my-sweet-deb'
|
9
|
+
version '77.0'
|
10
|
+
release '8'
|
11
|
+
pre_install "ls"
|
12
|
+
post_install "rd /s /q C:\*"
|
13
|
+
build_dir 'build/deb'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
let(:filename) { "build/deb/my-sweet-deb_77.0.8_x86_64.deb" }
|
17
|
+
#after { FileUtils.rm_rf(filename) }
|
18
|
+
|
19
|
+
[:package_name, :version, :release, :arch, :build_dir].each do |ivar|
|
20
|
+
context "when the #{ivar} is nil" do
|
21
|
+
before { subject.instance_variable_set(:"@#{ivar}", nil) }
|
22
|
+
it 'raises an error' do
|
23
|
+
expect { subject.create_package }.to raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when it has a foreman export' do
|
29
|
+
before do
|
30
|
+
subject.foreman do
|
31
|
+
name 'foreman'
|
32
|
+
init_dir '/etc/systemd/system'
|
33
|
+
build_dir 'build/foreman'
|
34
|
+
procfile File.join(File.dirname(__FILE__), '..', 'fixtures', 'Procfile')
|
35
|
+
user 'root'
|
36
|
+
type 'systemd'
|
37
|
+
prefix '/bin/sh'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'export the foreman to the deb' do
|
42
|
+
subject.create_package!
|
43
|
+
`dpkg --contents #{filename}`
|
44
|
+
.lines.grep(/foreman/).should_not be_empty
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when it has a docker', :docker do
|
49
|
+
before do
|
50
|
+
subject.docker do
|
51
|
+
name 'my-docker-for-deb'
|
52
|
+
import 'https://s3.amazonaws.com/swipely-pub/docker-export-ubuntu-latest.tgz'
|
53
|
+
git_archive '.'
|
54
|
+
build 'touch /deb_worked'
|
55
|
+
tag 'deb_test'
|
56
|
+
build_dir 'build/docker'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'builds the docker image and adds it to the deb' do
|
61
|
+
subject.create_package!
|
62
|
+
`dpkg --contents #{filename}`
|
63
|
+
.lines.grep(/dockly-deb_test-image\.tgz/).should_not be_empty
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when it has files' do
|
68
|
+
let(:file1) { Tempfile.new('files') }
|
69
|
+
let(:file2) { Tempfile.new('files') }
|
70
|
+
let(:contents) { `dpkg --contents #{filename}` }
|
71
|
+
|
72
|
+
before do
|
73
|
+
subject.file file1.path, '/etc/file1'
|
74
|
+
subject.file file2.path, '/etc/file2'
|
75
|
+
subject.file './lib/dockly/.', '/etc/deploys'
|
76
|
+
subject.file './lib/foreman/', '/etc/foreman'
|
77
|
+
subject.file './spec', '/etc/specs'
|
78
|
+
end
|
79
|
+
|
80
|
+
after do
|
81
|
+
file1.close
|
82
|
+
file1.unlink
|
83
|
+
|
84
|
+
file2.close
|
85
|
+
file2.unlink
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'adds the file to deb' do
|
89
|
+
subject.create_package!
|
90
|
+
expect(contents.lines.grep(/\/etc\/file1/)).to_not be_empty
|
91
|
+
expect(contents.lines.grep(/\/etc\/file2/)).to_not be_empty
|
92
|
+
expect(contents.lines.grep(/\/etc\/deploys\/deb.rb/)).to_not be_empty
|
93
|
+
expect(contents.lines.grep(/\/etc\/foreman\/foreman\/cli_fix.rb/)).to_not be_empty
|
94
|
+
expect(contents.lines.grep(/\/etc\/specs\/spec\/dockly_spec.rb/)).to_not be_empty
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when there is no docker or foreman export' do
|
99
|
+
it 'does nothing with docker or foreman' do
|
100
|
+
subject.docker.should_not_receive(:generate!)
|
101
|
+
subject.foreman.should_not_receive(:create!)
|
102
|
+
subject.create_package!
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'creates a deb package' do
|
106
|
+
subject.create_package!
|
107
|
+
File.exist?(subject.build_path).should be_true
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#exists?' do
|
113
|
+
subject do
|
114
|
+
Dockly::Deb.new do
|
115
|
+
package_name 'deb-4-u-buddy'
|
116
|
+
version '77.0'
|
117
|
+
release '8'
|
118
|
+
pre_install "ls"
|
119
|
+
post_install "rd /s /q C:\*"
|
120
|
+
build_dir 'build/deb/s3'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'when the object does exist' do
|
125
|
+
before do
|
126
|
+
Dockly::AWS.s3.stub(:head_object).and_return {}
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'is true' do
|
130
|
+
expect(subject.exists?).to be_true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when the object does not exist' do
|
135
|
+
before do
|
136
|
+
Dockly::AWS.s3.stub(:head_object).and_raise(Excon::Errors::NotFound.new "NotFound")
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'is true' do
|
140
|
+
expect(subject.exists?).to be_false
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe '#upload_to_s3' do
|
146
|
+
subject do
|
147
|
+
Dockly::Deb.new do
|
148
|
+
package_name 'deb-4-u-buddy'
|
149
|
+
version '77.0'
|
150
|
+
release '8'
|
151
|
+
pre_install "ls"
|
152
|
+
post_install "rd /s /q C:\*"
|
153
|
+
build_dir 'build/deb/s3'
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'when the s3_bucket is nil' do
|
158
|
+
it 'does nothing' do
|
159
|
+
Dockly::AWS.should_not_receive(:s3)
|
160
|
+
subject.upload_to_s3
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'when the s3_bucket is present' do
|
165
|
+
let(:bucket_name) { 'swerve_bucket' }
|
166
|
+
before { subject.s3_bucket(bucket_name) }
|
167
|
+
|
168
|
+
context 'when the package has yet to be created' do
|
169
|
+
before { FileUtils.rm(subject.build_path) rescue nil }
|
170
|
+
|
171
|
+
it 'creates it' do
|
172
|
+
subject.should_receive(:create_package!).and_call_original
|
173
|
+
subject.upload_to_s3
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'when the package has been created' do
|
178
|
+
before { subject.create_package! }
|
179
|
+
|
180
|
+
it 'creates the s3 bucket' do
|
181
|
+
subject.upload_to_s3
|
182
|
+
Dockly::AWS.s3.get_bucket(bucket_name).body.should_not be_nil
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'inserts the deb package into that bucket' do
|
186
|
+
subject.upload_to_s3
|
187
|
+
Dockly::AWS.s3.get_bucket(bucket_name, subject.s3_object_name).body.should_not be_nil
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "#file" do
|
194
|
+
subject do
|
195
|
+
Dockly::Deb.new do
|
196
|
+
package_name 'my-sweet-deb'
|
197
|
+
version '77.0'
|
198
|
+
release '8'
|
199
|
+
pre_install "ls"
|
200
|
+
post_install "rd /s /q C:\*"
|
201
|
+
build_dir 'build/deb'
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
before do
|
206
|
+
subject.files []
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'adds a hash of source and destination to the files list' do
|
210
|
+
subject.file('nginx.conf', '/etc/nginx.conf')
|
211
|
+
expect(subject.files).to eq([
|
212
|
+
{
|
213
|
+
:source => 'nginx.conf',
|
214
|
+
:destination => '/etc/nginx.conf'
|
215
|
+
}
|
216
|
+
])
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe '#build' do
|
221
|
+
subject do
|
222
|
+
Dockly::Deb.new do
|
223
|
+
package_name 'my-sweet-deb'
|
224
|
+
version '77.0'
|
225
|
+
release '8'
|
226
|
+
pre_install "ls"
|
227
|
+
post_install "rd /s /q C:\*"
|
228
|
+
build_dir 'build/deb'
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'calls create_package! and upload_to_s3' do
|
233
|
+
subject.should_receive(:create_package!)
|
234
|
+
subject.should_receive(:upload_to_s3)
|
235
|
+
subject.build
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|