beanstalkify 0.0.3 → 0.0.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/Gemfile.lock +1 -1
- data/README.md +2 -2
- data/bin/beanstalkify +8 -4
- data/lib/beanstalkify/application.rb +8 -12
- data/lib/beanstalkify/archive.rb +48 -18
- data/lib/beanstalkify/deployment_info.rb +1 -1
- data/lib/beanstalkify/environment.rb +27 -18
- data/lib/beanstalkify/version.rb +1 -1
- data/test/archive_spec.rb +75 -15
- data/test/environment_spec.rb +40 -0
- metadata +10 -3
- data/lib/beanstalkify/deploy.rb +0 -49
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -24,8 +24,8 @@ Should do the following
|
|
24
24
|
- Connect to aws using the credentials in `credentials.yml`
|
25
25
|
- Publish `app-version.zip` to s3
|
26
26
|
- Ensure that a beanstalk application called 'app' exists, and add a version called 'version', linked to the archive in that s3 bucket
|
27
|
-
- Ensure that the environment `env` exists (with optional settings overrides in `config.yml` - see below), running the specified stack.
|
28
|
-
- Deploy the provided version of the application into `env`
|
27
|
+
- Ensure that the environment `app-env` exists (with optional settings overrides in `config.yml` - see below), running the specified stack.
|
28
|
+
- Deploy the provided version of the application into `app-env`
|
29
29
|
- Report progress. When complete report the URL where the app can be hit (note: this will be the URL of the ELB).
|
30
30
|
|
31
31
|
# Settings overrides
|
data/bin/beanstalkify
CHANGED
@@ -3,6 +3,9 @@ require 'optparse'
|
|
3
3
|
require 'yaml'
|
4
4
|
Dir.glob(File.join(File.dirname(__FILE__), "../lib/beanstalkify", "*.rb")).each { |f| require f }
|
5
5
|
|
6
|
+
# Flush all logging immediately so that scripts invoking beanstalkify can choose to merge the info.
|
7
|
+
$stdout.sync = true
|
8
|
+
|
6
9
|
options = {}
|
7
10
|
OptionParser.new do |opts|
|
8
11
|
opts.on("-k", "--keyfile [file]", "Load credentials from yaml file") do |v|
|
@@ -27,17 +30,18 @@ end.parse!
|
|
27
30
|
|
28
31
|
required_params = [:credentials, :archive, :environment, :stack]
|
29
32
|
unless (required_params - options.keys).empty?
|
30
|
-
puts "Example usage: beanstalkify -k credentials.yml -a AppName-version.zip -e
|
33
|
+
puts "Example usage: beanstalkify -k credentials.yml -a AppName-version.zip -e Test -s '64bit Amazon Linux running Node.js' [-c config.yml] [-o info.yml]"
|
31
34
|
exit
|
32
35
|
end
|
33
36
|
|
34
37
|
Beanstalkify::Beanstalk.configure! options[:credentials]
|
35
38
|
|
36
39
|
app = Beanstalkify::Application.new(options[:stack], options[:config] || [])
|
37
|
-
|
38
|
-
environment = Beanstalkify::Environment.new(options[:environment])
|
40
|
+
archive = Beanstalkify::Archive.new(options[:archive])
|
41
|
+
environment = Beanstalkify::Environment.new(archive, options[:environment])
|
39
42
|
|
40
|
-
deployment_info = app.deploy!
|
43
|
+
deployment_info = app.deploy! archive, environment
|
41
44
|
|
42
45
|
File.open(options[:outfile], 'w') { |f| f.puts deployment_info.to_yaml } if options[:outfile]
|
43
46
|
|
47
|
+
raise("Deployed environment is not healthy") unless environment.healthy?
|
@@ -11,24 +11,20 @@ module Beanstalkify
|
|
11
11
|
|
12
12
|
# Deploy an archive to an environment.
|
13
13
|
# If the environment doesn't exist, it will be created.
|
14
|
-
def deploy!(
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
deployment.upload!
|
19
|
-
deployment.wait!
|
20
|
-
end
|
14
|
+
def deploy!(archive, env)
|
15
|
+
archive.upload(Beanstalk.api)
|
16
|
+
|
21
17
|
if env.status.empty?
|
22
|
-
puts "Creating stack '#{@stack}' for #{
|
23
|
-
env.create!(
|
18
|
+
puts "Creating stack '#{@stack}' for #{archive.app_name}-#{archive.version}..."
|
19
|
+
env.create!(archive, @stack, @config)
|
24
20
|
env.wait!("Launching")
|
25
21
|
else
|
26
|
-
puts "Deploying #{
|
27
|
-
env.deploy!(
|
22
|
+
puts "Deploying #{archive.version} to #{env.name}..."
|
23
|
+
env.deploy!(archive, @config)
|
28
24
|
env.wait!("Updating")
|
29
25
|
end
|
30
26
|
puts "Done. Visit http://#{env.url} in your browser."
|
31
|
-
DeploymentInfo.new env,
|
27
|
+
DeploymentInfo.new env, archive
|
32
28
|
end
|
33
29
|
end
|
34
30
|
end
|
data/lib/beanstalkify/archive.rb
CHANGED
@@ -1,23 +1,53 @@
|
|
1
|
+
require 'aws-sdk'
|
1
2
|
|
2
3
|
module Beanstalkify
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
f = filename
|
12
|
-
f[0..f.rindex('-')-1]
|
13
|
-
end
|
14
|
-
|
15
|
-
def version
|
16
|
-
File.basename(@path, '.*').split('-')[-1]
|
17
|
-
end
|
4
|
+
class Archive
|
5
|
+
attr_reader :app_name, :version
|
6
|
+
|
7
|
+
def initialize(filename)
|
8
|
+
@filename = filename
|
9
|
+
@archive_name = File.basename(@filename)
|
10
|
+
@app_name, hyphen, @version = File.basename(filename, '.*').rpartition("-")
|
11
|
+
end
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
|
13
|
+
def upload(beanstalk_api, s3_client=AWS::S3.new.client)
|
14
|
+
if already_uploaded?(beanstalk_api)
|
15
|
+
return puts "#{version} is already uploaded."
|
16
|
+
end
|
17
|
+
bucket = beanstalk_api.create_storage_location.data[:s3_bucket]
|
18
|
+
upload_to_s3(s3_client, bucket)
|
19
|
+
make_application_version_available_to_beanstalk(beanstalk_api, bucket)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def upload_to_s3(s3_client, bucket)
|
25
|
+
puts "Uploading #{@archive_name} to bucket #{bucket}..."
|
26
|
+
s3_client.put_object(
|
27
|
+
bucket_name: bucket,
|
28
|
+
key: @archive_name,
|
29
|
+
data: File.open(@filename)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def make_application_version_available_to_beanstalk(beanstalk_api, bucket)
|
34
|
+
puts "Making version #{version} of #{app_name} available to Beanstalk..."
|
35
|
+
beanstalk_api.create_application_version(
|
36
|
+
application_name: app_name,
|
37
|
+
version_label: version,
|
38
|
+
source_bundle: {
|
39
|
+
s3_bucket: bucket,
|
40
|
+
s3_key: @archive_name
|
41
|
+
},
|
42
|
+
auto_create_application: true
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def already_uploaded?(beanstalk_api)
|
47
|
+
beanstalk_api.describe_application_versions(
|
48
|
+
application_name: app_name,
|
49
|
+
version_labels: [version]
|
50
|
+
).data[:application_versions].count > 0
|
22
51
|
end
|
52
|
+
end
|
23
53
|
end
|
@@ -4,8 +4,8 @@ module Beanstalkify
|
|
4
4
|
class Environment
|
5
5
|
attr_accessor :name
|
6
6
|
|
7
|
-
def initialize(name)
|
8
|
-
@name = name
|
7
|
+
def initialize(archive, name)
|
8
|
+
@name = [archive.app_name, name].join("-")
|
9
9
|
@beanstalk = Beanstalk.api
|
10
10
|
end
|
11
11
|
|
@@ -20,12 +20,12 @@ module Beanstalkify
|
|
20
20
|
})
|
21
21
|
end
|
22
22
|
|
23
|
-
# Assuming the
|
23
|
+
# Assuming the archive has already been uploaded,
|
24
24
|
# create a new environment with the app deployed onto the provided stack.
|
25
|
-
def create!(
|
25
|
+
def create!(archive, stack, settings=[])
|
26
26
|
@beanstalk.create_environment({
|
27
|
-
:application_name =>
|
28
|
-
:version_label =>
|
27
|
+
:application_name => archive.app_name,
|
28
|
+
:version_label => archive.version,
|
29
29
|
:environment_name => self.name,
|
30
30
|
:solution_stack_name => stack,
|
31
31
|
:option_settings => settings
|
@@ -33,28 +33,37 @@ module Beanstalkify
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def status
|
36
|
-
|
37
|
-
:environment_names => [self.name],
|
38
|
-
:include_deleted => false
|
39
|
-
}).data[:environments]
|
40
|
-
e = envs.first
|
36
|
+
e = describe_environment
|
41
37
|
e ? e[:status] : ""
|
42
38
|
end
|
43
39
|
|
44
40
|
def url
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
e = describe_environment
|
42
|
+
e ? e[:cname] : ""
|
43
|
+
end
|
44
|
+
|
45
|
+
def healthy?
|
46
|
+
e = describe_environment
|
47
|
+
e ? e[:health] == 'Green' : false
|
50
48
|
end
|
51
49
|
|
52
50
|
# Wait for the status to change from `old_status` to something else
|
53
51
|
def wait!(old_status)
|
52
|
+
puts "Waiting for #{self.name} to finish #{old_status.downcase}..."
|
54
53
|
while self.status == old_status
|
55
|
-
|
56
|
-
sleep
|
54
|
+
print '.'
|
55
|
+
sleep 5
|
57
56
|
end
|
57
|
+
puts
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def describe_environment
|
63
|
+
@beanstalk.describe_environments({
|
64
|
+
:environment_names => [name],
|
65
|
+
:include_deleted => false
|
66
|
+
}).data[:environments].first
|
58
67
|
end
|
59
68
|
end
|
60
69
|
end
|
data/lib/beanstalkify/version.rb
CHANGED
data/test/archive_spec.rb
CHANGED
@@ -1,26 +1,86 @@
|
|
1
|
-
|
2
1
|
require './lib/beanstalkify/archive'
|
3
2
|
|
4
3
|
describe Beanstalkify::Archive do
|
5
|
-
|
4
|
+
ARCHIVE_FILENAME = '/path/to/my/archive/app-name-version.zip'
|
5
|
+
|
6
6
|
before do
|
7
|
-
archive = Beanstalkify::Archive.new
|
7
|
+
@archive = Beanstalkify::Archive.new ARCHIVE_FILENAME
|
8
8
|
end
|
9
|
+
|
10
|
+
describe 'parsing the filename' do
|
11
|
+
it 'extracts the application name from the filename' do
|
12
|
+
@archive.app_name.should eq('app-name')
|
13
|
+
end
|
9
14
|
|
10
|
-
|
11
|
-
|
15
|
+
it 'extracts the archive version from the filename' do
|
16
|
+
@archive.version.should eq('version')
|
17
|
+
end
|
12
18
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
19
|
+
|
20
|
+
describe 'uploading to AWS' do
|
21
|
+
before(:each) do
|
22
|
+
@beanstalk_api = double(
|
23
|
+
create_storage_location: double(
|
24
|
+
data: {s3_bucket: 'mah bukkit'}
|
25
|
+
)
|
26
|
+
).as_null_object
|
27
|
+
@s3_client = double.as_null_object
|
28
|
+
allow(File).to receive(:open).with(ARCHIVE_FILENAME).and_return("fake archive file contents")
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'knows if it has already been uploaded' do
|
32
|
+
when_beanstalk_describe_application_versions_returns([])
|
33
|
+
@archive.send(:already_uploaded?, @beanstalk_api).should be_false
|
34
|
+
when_beanstalk_describe_application_versions_returns(["some version or other"])
|
35
|
+
@archive.send(:already_uploaded?, @beanstalk_api).should be_true
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when it has already been uploaded" do
|
39
|
+
before(:each) do
|
40
|
+
allow(@archive).to receive(:already_uploaded?).and_return true
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'does not re-upload' do
|
44
|
+
expect(@s3_client).to_not receive(:put_object)
|
45
|
+
expect(@beanstalk_api).to_not receive(:create_application_version)
|
46
|
+
@archive.upload @beanstalk_api, @s3_client
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when it hasn't already been uploaded" do
|
51
|
+
before(:each) do
|
52
|
+
allow(@archive).to receive(:already_uploaded?).and_return false
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'uploads the file to S3' do
|
56
|
+
expect(@s3_client).to receive(:put_object).with(
|
57
|
+
bucket_name: 'mah bukkit',
|
58
|
+
key: 'app-name-version.zip',
|
59
|
+
data: "fake archive file contents"
|
60
|
+
)
|
61
|
+
@archive.upload @beanstalk_api, @s3_client
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'creates an available application version' do
|
65
|
+
expect(@beanstalk_api).to receive(:create_application_version).with(
|
66
|
+
application_name: "app-name",
|
67
|
+
version_label: "version",
|
68
|
+
source_bundle: {
|
69
|
+
s3_bucket: "mah bukkit",
|
70
|
+
s3_key: "app-name-version.zip"
|
71
|
+
},
|
72
|
+
auto_create_application: true
|
73
|
+
)
|
74
|
+
@archive.upload @beanstalk_api, @s3_client
|
75
|
+
end
|
76
|
+
end
|
16
77
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
archive.filename.should eq('app-name-version.zip')
|
78
|
+
|
79
|
+
def when_beanstalk_describe_application_versions_returns(versions)
|
80
|
+
expect(@beanstalk_api).to receive(:describe_application_versions).with(
|
81
|
+
application_name: "app-name",
|
82
|
+
version_labels: ["version"]
|
83
|
+
).and_return(double(data: {application_versions: versions}))
|
24
84
|
end
|
25
85
|
end
|
26
86
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require './lib/beanstalkify/archive'
|
2
|
+
require './lib/beanstalkify/environment'
|
3
|
+
|
4
|
+
describe Beanstalkify::Environment do
|
5
|
+
before do
|
6
|
+
allow(Beanstalkify::Beanstalk).to receive(:api).and_return @beanstalk_api = double
|
7
|
+
archive = Beanstalkify::Archive.new '/path/to/my/archive/app-name-version.zip'
|
8
|
+
@env = Beanstalkify::Environment.new archive, "Test"
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'prepends the application name because environment names must be unique within an AWS account' do
|
12
|
+
@env.name.should == "app-name-Test"
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'exposes the Beanstalk status' do
|
16
|
+
when_beanstalk_describe_environments_returns(status: 'Uncertain')
|
17
|
+
@env.status.should == 'Uncertain'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'exposes the Beanstalk CNAME URL' do
|
21
|
+
when_beanstalk_describe_environments_returns(cname: 'http://cname.elasticbeanstalk.com')
|
22
|
+
@env.url.should == 'http://cname.elasticbeanstalk.com'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'is healthy when Beanstalk reports that it is green' do
|
26
|
+
when_beanstalk_describe_environments_returns(health: 'Red')
|
27
|
+
@env.should_not be_healthy
|
28
|
+
when_beanstalk_describe_environments_returns(health: 'Green')
|
29
|
+
@env.should be_healthy
|
30
|
+
end
|
31
|
+
|
32
|
+
def when_beanstalk_describe_environments_returns(env_data)
|
33
|
+
expect(@beanstalk_api).to receive(:describe_environments).with(
|
34
|
+
environment_names: ["app-name-Test"],
|
35
|
+
include_deleted: false
|
36
|
+
).and_return double(
|
37
|
+
data: {environments: [env_data]}
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beanstalkify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|
@@ -62,12 +62,12 @@ files:
|
|
62
62
|
- lib/beanstalkify/application.rb
|
63
63
|
- lib/beanstalkify/archive.rb
|
64
64
|
- lib/beanstalkify/beanstalk.rb
|
65
|
-
- lib/beanstalkify/deploy.rb
|
66
65
|
- lib/beanstalkify/deployment_info.rb
|
67
66
|
- lib/beanstalkify/environment.rb
|
68
67
|
- lib/beanstalkify/version.rb
|
69
68
|
- test/archive_spec.rb
|
70
69
|
- test/deployment_info_spec.rb
|
70
|
+
- test/environment_spec.rb
|
71
71
|
homepage: https://github.com/pranavraja/beanstalkify
|
72
72
|
licenses:
|
73
73
|
- MIT
|
@@ -81,12 +81,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
81
|
- - ! '>='
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
hash: -4062555010533808231
|
84
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
88
|
none: false
|
86
89
|
requirements:
|
87
90
|
- - ! '>='
|
88
91
|
- !ruby/object:Gem::Version
|
89
92
|
version: '0'
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
hash: -4062555010533808231
|
90
96
|
requirements: []
|
91
97
|
rubyforge_project:
|
92
98
|
rubygems_version: 1.8.24
|
@@ -96,3 +102,4 @@ summary: Beanstalk automation for dummies
|
|
96
102
|
test_files:
|
97
103
|
- test/archive_spec.rb
|
98
104
|
- test/deployment_info_spec.rb
|
105
|
+
- test/environment_spec.rb
|
data/lib/beanstalkify/deploy.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'beanstalkify/archive'
|
2
|
-
require 'beanstalkify/beanstalk'
|
3
|
-
require 'aws-sdk'
|
4
|
-
|
5
|
-
module Beanstalkify
|
6
|
-
class Deploy
|
7
|
-
attr_accessor :beanstalk, :archive
|
8
|
-
|
9
|
-
def initialize(path)
|
10
|
-
@archive = Archive.new(path)
|
11
|
-
@beanstalk = Beanstalk.api
|
12
|
-
end
|
13
|
-
|
14
|
-
def bucket
|
15
|
-
@beanstalk.create_storage_location.data[:s3_bucket]
|
16
|
-
end
|
17
|
-
|
18
|
-
def upload!
|
19
|
-
client = AWS::S3.new.client
|
20
|
-
bucket = self.bucket
|
21
|
-
puts "Uploading #{@archive.filename} to bucket #{bucket}..."
|
22
|
-
client.put_object({ :bucket_name => bucket, :key => @archive.filename, :data => File.open(@archive.path) })
|
23
|
-
puts "Creating #{@archive.name} - #{@archive.version} in beanstalk"
|
24
|
-
@beanstalk.create_application_version({
|
25
|
-
:application_name => @archive.name,
|
26
|
-
:version_label => @archive.version,
|
27
|
-
:source_bundle => {
|
28
|
-
:s3_bucket => bucket,
|
29
|
-
:s3_key => @archive.filename
|
30
|
-
},
|
31
|
-
:auto_create_application => true
|
32
|
-
})
|
33
|
-
end
|
34
|
-
|
35
|
-
def deployed?
|
36
|
-
@beanstalk.describe_application_versions({
|
37
|
-
:application_name => @archive.name,
|
38
|
-
:version_labels => [@archive.version]
|
39
|
-
}).data[:application_versions].count > 0
|
40
|
-
end
|
41
|
-
|
42
|
-
def wait!
|
43
|
-
while not self.deployed?
|
44
|
-
puts "Waiting for #{@archive.version} to be available..."
|
45
|
-
sleep 10
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|