dockly 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,3 @@
1
+ module Dockly
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'foreman/cli'
2
+
3
+ class Foreman::CLI
4
+ private
5
+ # Because are you serious foreman????
6
+ def error(message)
7
+ raise "ERROR: #{message}"
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ require 'foreman/export/base'
2
+
3
+ class Foreman::Export::Base
4
+ def export
5
+ end
6
+ 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