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.
@@ -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