heirloom 0.1.3 → 0.1.4
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.
- data/CHANGELOG +6 -0
- data/README.md +0 -1
- data/lib/heirloom/acl/s3.rb +10 -8
- data/lib/heirloom/artifact.rb +44 -43
- data/lib/heirloom/artifact/artifact_authorizer.rb +20 -22
- data/lib/heirloom/artifact/artifact_builder.rb +41 -37
- data/lib/heirloom/artifact/artifact_destroyer.rb +16 -14
- data/lib/heirloom/artifact/artifact_downloader.rb +22 -40
- data/lib/heirloom/artifact/artifact_lister.rb +10 -7
- data/lib/heirloom/artifact/artifact_reader.rb +17 -20
- data/lib/heirloom/artifact/artifact_updater.rb +6 -5
- data/lib/heirloom/artifact/artifact_uploader.rb +8 -8
- data/lib/heirloom/aws/s3.rb +1 -1
- data/lib/heirloom/cli.rb +37 -30
- data/lib/heirloom/cli/build.rb +40 -0
- data/lib/heirloom/cli/destroy.rb +20 -0
- data/lib/heirloom/cli/download.rb +23 -0
- data/lib/heirloom/cli/list.rb +17 -0
- data/lib/heirloom/cli/show.rb +27 -0
- data/lib/heirloom/cli/update.rb +23 -0
- data/lib/heirloom/config.rb +11 -6
- data/lib/heirloom/destroyer/s3.rb +6 -4
- data/lib/heirloom/directory/directory.rb +15 -11
- data/lib/heirloom/directory/git_directory.rb +4 -3
- data/lib/heirloom/downloader/s3.rb +1 -1
- data/lib/heirloom/logger.rb +6 -4
- data/lib/heirloom/version.rb +1 -1
- data/spec/acl/s3_spec.rb +51 -0
- data/spec/artifact/artifact_authorizer_spec.rb +34 -0
- data/spec/artifact/artifact_builder_spec.rb +41 -0
- data/spec/artifact/artifact_destroyer_spec.rb +45 -0
- data/spec/artifact/artifact_downloader_spec.rb +93 -0
- data/spec/artifact/artifact_lister_spec.rb +21 -0
- data/spec/artifact/artifact_reader_spec.rb +55 -0
- data/spec/artifact/artifact_updater_spec.rb +16 -0
- data/spec/artifact/artifact_uploader_spec.rb +16 -0
- data/spec/artifact_spec.rb +69 -19
- data/spec/aws/s3_spec.rb +55 -0
- data/spec/aws/simpledb_spec.rb +50 -0
- data/spec/config_spec.rb +32 -3
- data/spec/destroyer/s3_spec.rb +21 -0
- data/spec/directory/directory_spec.rb +26 -0
- data/spec/directory/git_directory_spec.rb +28 -0
- data/spec/downloader/s3_spec.rb +23 -0
- data/spec/logger_spec.rb +20 -0
- metadata +55 -16
@@ -2,9 +2,11 @@ module Heirloom
|
|
2
2
|
module Destroyer
|
3
3
|
class S3
|
4
4
|
|
5
|
+
attr_accessor :config, :region
|
6
|
+
|
5
7
|
def initialize(args)
|
6
|
-
|
7
|
-
|
8
|
+
self.config = args[:config]
|
9
|
+
self.region = args[:region]
|
8
10
|
end
|
9
11
|
|
10
12
|
def destroy_file(args)
|
@@ -18,8 +20,8 @@ module Heirloom
|
|
18
20
|
private
|
19
21
|
|
20
22
|
def s3
|
21
|
-
@s3 ||= AWS::S3.new :config =>
|
22
|
-
:region =>
|
23
|
+
@s3 ||= AWS::S3.new :config => config,
|
24
|
+
:region => region
|
23
25
|
end
|
24
26
|
|
25
27
|
end
|
@@ -8,32 +8,36 @@ module Heirloom
|
|
8
8
|
|
9
9
|
class Directory
|
10
10
|
|
11
|
+
attr_accessor :config, :exclude, :local_build, :path, :logger
|
12
|
+
|
11
13
|
def initialize(args)
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
self.config = args[:config]
|
15
|
+
self.exclude = args[:exclude]
|
16
|
+
self.path = args[:path]
|
17
|
+
self.logger = config.logger
|
15
18
|
end
|
16
19
|
|
17
20
|
def build_artifact_from_directory
|
18
21
|
random_text = (0...8).map{65.+(rand(25)).chr}.join
|
19
|
-
temp_file_name = File.join(Dir.tmpdir, random_text + ".tar.gz")
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
unless local_build
|
24
|
+
self.local_build = File.join(Dir.tmpdir, random_text + ".tar.gz")
|
25
|
+
end
|
26
|
+
|
27
|
+
logger.info "Building artifact '#{local_build}' from '#{path}'."
|
28
|
+
logger.info "Excluding #{exclude.to_s}."
|
29
|
+
logger.info "Adding #{files_to_pack.to_s}."
|
24
30
|
|
25
|
-
tgz = Zlib::GzipWriter.new File.open(
|
31
|
+
tgz = Zlib::GzipWriter.new File.open(local_build, 'wb')
|
26
32
|
|
27
33
|
Minitar.pack(files_to_pack, tgz)
|
28
|
-
temp_file_name
|
29
34
|
end
|
30
35
|
|
31
36
|
private
|
32
37
|
|
33
38
|
def files_to_pack
|
34
|
-
Dir.entries(
|
39
|
+
Dir.entries(path) - ['.', '..'] - exclude
|
35
40
|
end
|
36
41
|
|
37
|
-
|
38
42
|
end
|
39
43
|
end
|
@@ -6,13 +6,14 @@ module Heirloom
|
|
6
6
|
|
7
7
|
class GitDirectory
|
8
8
|
|
9
|
+
attr_accessor :path
|
10
|
+
|
9
11
|
def initialize(args)
|
10
|
-
|
11
|
-
@logger = args[:logger]
|
12
|
+
self.path = args[:path]
|
12
13
|
end
|
13
14
|
|
14
15
|
def commit(sha = nil)
|
15
|
-
r = Repo.new
|
16
|
+
r = Repo.new path
|
16
17
|
sha ? r.commits(sha).first : r.commits.first
|
17
18
|
end
|
18
19
|
|
data/lib/heirloom/logger.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
module Heirloom
|
2
2
|
class HeirloomLogger
|
3
3
|
|
4
|
-
def initialize(args)
|
4
|
+
def initialize(args = {})
|
5
5
|
@logger = args[:logger] ||= Logger.new(STDOUT)
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
unless args[:logger]
|
8
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
9
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
10
|
+
"#{datetime}: #{msg}\n"
|
11
|
+
end
|
10
12
|
end
|
11
13
|
|
12
14
|
@logger
|
data/lib/heirloom/version.rb
CHANGED
data/spec/acl/s3_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heirloom do
|
4
|
+
before do
|
5
|
+
@config_mock = double 'config'
|
6
|
+
@logger_mock = double 'logger'
|
7
|
+
@config_mock.should_receive(:logger).and_return(@logger_mock)
|
8
|
+
@config_mock.should_receive(:authorized_aws_accounts).
|
9
|
+
and_return ['acct1@test.com', 'acct2@test.com']
|
10
|
+
|
11
|
+
@s3 = Heirloom::ACL::S3.new :config => @config_mock,
|
12
|
+
:region => 'us-west-1'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should allow read access for the specified accounts" do
|
16
|
+
acls = {
|
17
|
+
'Owner' => {
|
18
|
+
'Name' => 'Brett',
|
19
|
+
'ID' => '123'
|
20
|
+
}
|
21
|
+
}
|
22
|
+
s3_mock = mock 's3'
|
23
|
+
|
24
|
+
@s3.should_receive(:s3).exactly(2).times.
|
25
|
+
and_return(s3_mock)
|
26
|
+
|
27
|
+
s3_mock.should_receive(:get_bucket_acl).with('bucket').
|
28
|
+
and_return acls
|
29
|
+
|
30
|
+
grants_mock = mock 'grants'
|
31
|
+
@s3.should_receive(:build_bucket_grants).
|
32
|
+
with(:id => '123',
|
33
|
+
:name => 'Brett',
|
34
|
+
:accounts => ['acct1@test.com', 'acct2@test.com']).
|
35
|
+
and_return grants_mock
|
36
|
+
|
37
|
+
@logger_mock.should_receive(:info).
|
38
|
+
with 'Authorizing acct1@test.com to s3://bucket/key-folder/key.tar.gz.'
|
39
|
+
@logger_mock.should_receive(:info).
|
40
|
+
with 'Authorizing acct2@test.com to s3://bucket/key-folder/key.tar.gz.'
|
41
|
+
|
42
|
+
s3_mock.should_receive(:put_object_acl).with('bucket', 'key-folder/key.tar.gz', grants_mock)
|
43
|
+
|
44
|
+
@s3.allow_read_access_from_accounts :bucket => 'bucket',
|
45
|
+
:key_name => 'key',
|
46
|
+
:key_folder => 'key-folder'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should test build_bucket_grants private method"
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heirloom do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config_mock = double('config')
|
7
|
+
@logger_mock = double('logger')
|
8
|
+
@config_mock.should_receive(:logger).and_return(@logger_mock)
|
9
|
+
@authorizer = Heirloom::ArtifactAuthorizer.new :config => @config_mock,
|
10
|
+
:name => 'tim',
|
11
|
+
:id => '123'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should authorize access to an acl across all regions" do
|
15
|
+
artifact_reader = double
|
16
|
+
s3_acl = double
|
17
|
+
@logger_mock.should_receive(:info).exactly(2).times
|
18
|
+
@config_mock.should_receive(:regions).
|
19
|
+
and_return(['us-west-1', 'us-west-2'])
|
20
|
+
@authorizer.should_receive(:artifact_reader).exactly(2).times.
|
21
|
+
and_return(artifact_reader)
|
22
|
+
artifact_reader.should_receive(:get_bucket).exactly(2).times.
|
23
|
+
and_return('the-bucket')
|
24
|
+
Heirloom::ACL::S3.should_receive(:new).exactly(2).
|
25
|
+
times.and_return(s3_acl)
|
26
|
+
s3_acl.should_receive(:allow_read_access_from_accounts).
|
27
|
+
exactly(2).times.
|
28
|
+
with(:key_name => '123',
|
29
|
+
:key_folder => 'tim',
|
30
|
+
:bucket => 'the-bucket')
|
31
|
+
@authorizer.authorize
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heirloom do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config_mock = double 'config'
|
7
|
+
@logger_mock = double 'logger'
|
8
|
+
@simpledb_mock = double 'simple db'
|
9
|
+
@config_mock.should_receive(:logger).and_return(@logger_mock)
|
10
|
+
Heirloom::AWS::SimpleDB.should_receive(:new).with(:config => @config_mock).
|
11
|
+
and_return(@simpledb_mock)
|
12
|
+
@simpledb_mock.should_receive(:create_domain).with 'tim'
|
13
|
+
@builder = Heirloom::ArtifactBuilder.new :config => @config_mock,
|
14
|
+
:name => 'tim',
|
15
|
+
:id => '123'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should build an artifact" do
|
19
|
+
directory_mock = double "directory"
|
20
|
+
Heirloom::Directory.should_receive(:new).with(:path => 'path_to_build',
|
21
|
+
:exclude => ['.dir_to_exclude'],
|
22
|
+
:config => @config_mock).
|
23
|
+
and_return(directory_mock)
|
24
|
+
directory_mock.should_receive :build_artifact_from_directory
|
25
|
+
directory_mock.should_receive(:local_build).and_return('/tmp/file')
|
26
|
+
@builder.should_receive(:create_artifact_record)
|
27
|
+
@builder.should_receive(:add_git_commit)
|
28
|
+
@logger_mock.should_receive(:info).with("Build complete.")
|
29
|
+
@builder.build(:exclude => ['.dir_to_exclude'],
|
30
|
+
:directory => 'path_to_build',
|
31
|
+
:git => 'true').should == '/tmp/file'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should cleanup the local artifact" do
|
35
|
+
@builder.local_build = '/tmp/file'
|
36
|
+
@logger_mock.should_receive(:info).with("Cleaning up local build /tmp/file.")
|
37
|
+
File.should_receive(:delete).with('/tmp/file')
|
38
|
+
@builder.cleanup
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heirloom do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config_mock = double 'config'
|
7
|
+
@logger_mock = double 'logger'
|
8
|
+
@config_mock.should_receive(:logger).and_return(@logger_mock)
|
9
|
+
@destroyer = Heirloom::ArtifactDestroyer.new :config => @config_mock,
|
10
|
+
:name => 'tim',
|
11
|
+
:id => '123'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should destroy the given artifact" do
|
15
|
+
@logger_mock.should_receive(:info).
|
16
|
+
with "Destroying tim - 123"
|
17
|
+
@config_mock.should_receive(:regions).and_return ['us-west-1']
|
18
|
+
artifact_reader_mock = mock 'artifact reader'
|
19
|
+
@destroyer.should_receive(:artifact_reader).and_return artifact_reader_mock
|
20
|
+
bucket_mock = mock 'bucket'
|
21
|
+
artifact_reader_mock.should_receive(:get_bucket).
|
22
|
+
with(:region => 'us-west-1').
|
23
|
+
and_return 'bucket-us-west-1'
|
24
|
+
|
25
|
+
@logger_mock.should_receive(:info).
|
26
|
+
with "Destroying 's3://bucket-us-west-1/tim/123.tar.gz'."
|
27
|
+
|
28
|
+
s3_destroyer_mock = mock 's3 destroyer'
|
29
|
+
Heirloom::Destroyer::S3.should_receive(:new).
|
30
|
+
with(:config => @config_mock,
|
31
|
+
:region => 'us-west-1').
|
32
|
+
and_return s3_destroyer_mock
|
33
|
+
s3_destroyer_mock.should_receive(:destroy_file).
|
34
|
+
with :key_name => '123.tar.gz',
|
35
|
+
:key_folder => 'tim',
|
36
|
+
:bucket => 'bucket-us-west-1'
|
37
|
+
sdb_mock = mock 'sdb'
|
38
|
+
@destroyer.should_receive(:sdb).and_return sdb_mock
|
39
|
+
sdb_mock.should_receive(:delete).with 'tim', '123'
|
40
|
+
@logger_mock.should_receive(:info).
|
41
|
+
with "Destroy complete."
|
42
|
+
@destroyer.destroy
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heirloom do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config_mock = double 'config'
|
7
|
+
@logger_mock = double 'logger'
|
8
|
+
@config_mock.should_receive(:logger).and_return(@logger_mock)
|
9
|
+
@downloader = Heirloom::ArtifactDownloader.new :config => @config_mock,
|
10
|
+
:name => 'tim',
|
11
|
+
:id => '123'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should download an artifact" do
|
15
|
+
s3_downloader_mock = mock 's3 downloader'
|
16
|
+
Heirloom::Downloader::S3.should_receive(:new).
|
17
|
+
with(:config => @config_mock,
|
18
|
+
:logger => @logger_mock,
|
19
|
+
:region => 'us-west-1').
|
20
|
+
and_return s3_downloader_mock
|
21
|
+
artifact_reader_mock = mock 'artifact_reader'
|
22
|
+
@downloader.should_receive(:artifact_reader).
|
23
|
+
exactly(2).times.
|
24
|
+
and_return artifact_reader_mock
|
25
|
+
artifact_reader_mock.should_receive(:get_bucket).
|
26
|
+
with(:region => 'us-west-1').
|
27
|
+
and_return 'bucket-us-west-1'
|
28
|
+
artifact_reader_mock.should_receive(:get_key).
|
29
|
+
with(:region => 'us-west-1').
|
30
|
+
and_return 'key'
|
31
|
+
|
32
|
+
@logger_mock.should_receive(:info).
|
33
|
+
with "Downloading s3://bucket-us-west-1/key from us-west-1."
|
34
|
+
|
35
|
+
s3_downloader_mock.should_receive(:download_file).
|
36
|
+
with(:bucket => 'bucket-us-west-1',
|
37
|
+
:key => 'key').
|
38
|
+
and_return 'filename'
|
39
|
+
|
40
|
+
@logger_mock.should_receive(:info).
|
41
|
+
with "Writing file to /tmp/file."
|
42
|
+
|
43
|
+
file_mock = mock 'file'
|
44
|
+
|
45
|
+
File.should_receive(:open).with('/tmp/file', 'w').
|
46
|
+
and_return file_mock
|
47
|
+
|
48
|
+
@logger_mock.should_receive(:info).with "Download complete."
|
49
|
+
|
50
|
+
@downloader.download(:output => '/tmp/file',
|
51
|
+
:region => 'us-west-1')
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should download the artifact to the current path if output is unspecficief" do
|
55
|
+
s3_downloader_mock = mock 's3 downloader'
|
56
|
+
Heirloom::Downloader::S3.should_receive(:new).
|
57
|
+
with(:config => @config_mock,
|
58
|
+
:logger => @logger_mock,
|
59
|
+
:region => 'us-west-1').
|
60
|
+
and_return s3_downloader_mock
|
61
|
+
artifact_reader_mock = mock 'artifact_reader'
|
62
|
+
@downloader.should_receive(:artifact_reader).
|
63
|
+
exactly(2).times.
|
64
|
+
and_return artifact_reader_mock
|
65
|
+
artifact_reader_mock.should_receive(:get_bucket).
|
66
|
+
with(:region => 'us-west-1').
|
67
|
+
and_return 'bucket-us-west-1'
|
68
|
+
artifact_reader_mock.should_receive(:get_key).
|
69
|
+
with(:region => 'us-west-1').
|
70
|
+
and_return 'key'
|
71
|
+
|
72
|
+
@logger_mock.should_receive(:info).
|
73
|
+
with "Downloading s3://bucket-us-west-1/key from us-west-1."
|
74
|
+
|
75
|
+
s3_downloader_mock.should_receive(:download_file).
|
76
|
+
with(:bucket => 'bucket-us-west-1',
|
77
|
+
:key => 'key').
|
78
|
+
and_return 'filename'
|
79
|
+
|
80
|
+
@logger_mock.should_receive(:info).
|
81
|
+
with "Writing file to ./key."
|
82
|
+
|
83
|
+
file_mock = mock 'file'
|
84
|
+
|
85
|
+
File.should_receive(:open).with('./key', 'w').
|
86
|
+
and_return file_mock
|
87
|
+
|
88
|
+
@logger_mock.should_receive(:info).with "Download complete."
|
89
|
+
|
90
|
+
@downloader.download(:region => 'us-west-1')
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heirloom do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config_mock = double 'config'
|
7
|
+
@lister = Heirloom::ArtifactLister.new :config => @config_mock,
|
8
|
+
:name => 'test123'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should list the known artifacts" do
|
12
|
+
sdb_mock = mock 'sdb'
|
13
|
+
@lister.should_receive(:sdb).and_return sdb_mock
|
14
|
+
sdb_mock.should_receive(:select).
|
15
|
+
with("select * from test123 where built_at > '2000-01-01T00:00:00.000Z' \
|
16
|
+
order by built_at desc limit 10").
|
17
|
+
and_return( {'1' => 'one', '2' => 'two', '3' => 'three'} )
|
18
|
+
@lister.list.should == ['1', '2', '3']
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heirloom do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config_mock = double 'config'
|
7
|
+
@reader = Heirloom::ArtifactReader.new :config => @config_mock,
|
8
|
+
:name => 'tim',
|
9
|
+
:id => '123'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should show the item record" do
|
13
|
+
sdb_mock = mock 'sdb'
|
14
|
+
@reader.should_receive(:sdb).and_return sdb_mock
|
15
|
+
sdb_mock.should_receive(:select).
|
16
|
+
with("select * from tim where itemName() = '123'").
|
17
|
+
and_return( { '123' => 'details' } )
|
18
|
+
@reader.show.should == 'details'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return true if the record exists" do
|
22
|
+
@reader.should_receive(:show).and_return 'a record'
|
23
|
+
@reader.exists?.should == true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return false if the recrod does not exist" do
|
27
|
+
@reader.should_receive(:show).and_return nil
|
28
|
+
@reader.exists?.should == false
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return the bucket for the specified region" do
|
32
|
+
@reader.should_receive(:get_url).
|
33
|
+
with(:region => 'us-west-1').
|
34
|
+
and_return 's3://bucket-us-west-1/tim/123.tar.gz'
|
35
|
+
@reader.get_bucket(:region => 'us-west-1').should == 'bucket-us-west-1'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return the key" do
|
39
|
+
@reader.should_receive(:show).
|
40
|
+
and_return( { 'us-west-1-s3-url' =>
|
41
|
+
[ 's3://bucket-us-west-1/tim/123.tar.gz' ] } )
|
42
|
+
@reader.should_receive(:get_bucket).
|
43
|
+
with(:region => 'us-west-1').
|
44
|
+
and_return 'bucket-us-west-1'
|
45
|
+
@reader.get_key(:region => 'us-west-1').should == 'tim/123.tar.gz'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "shoudl return the s3 url for the given region" do
|
49
|
+
@reader.should_receive(:show).
|
50
|
+
and_return( { 'us-west-1-s3-url' =>
|
51
|
+
[ 's3://bucket-us-west-1/tim/123.tar.gz' ] } )
|
52
|
+
@reader.get_url(:region => 'us-west-1').should == 's3://bucket-us-west-1/tim/123.tar.gz'
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|