ey_cli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +57 -0
- data/LICENSE +22 -0
- data/README.md +104 -0
- data/Rakefile +129 -0
- data/bin/ey_cli +5 -0
- data/ey_cli.gemspec +117 -0
- data/history.md +3 -0
- data/lib/ey_cli/api.rb +96 -0
- data/lib/ey_cli/cli.rb +17 -0
- data/lib/ey_cli/command_manager.rb +29 -0
- data/lib/ey_cli/commands/accounts.rb +26 -0
- data/lib/ey_cli/commands/apps.rb +24 -0
- data/lib/ey_cli/commands/base.rb +16 -0
- data/lib/ey_cli/commands/console.rb +38 -0
- data/lib/ey_cli/commands/create_app.rb +76 -0
- data/lib/ey_cli/commands/create_env.rb +106 -0
- data/lib/ey_cli/commands/deploy.rb +23 -0
- data/lib/ey_cli/commands/help.rb +65 -0
- data/lib/ey_cli/commands/show.rb +65 -0
- data/lib/ey_cli/controllers/accounts.rb +23 -0
- data/lib/ey_cli/controllers/apps.rb +66 -0
- data/lib/ey_cli/controllers/environments.rb +78 -0
- data/lib/ey_cli/git_utils.rb +12 -0
- data/lib/ey_cli/models/account.rb +6 -0
- data/lib/ey_cli/models/app.rb +15 -0
- data/lib/ey_cli/models/base.rb +54 -0
- data/lib/ey_cli/models/environment.rb +32 -0
- data/lib/ey_cli/options_parser.rb +47 -0
- data/lib/ey_cli/smarty_parser.rb +29 -0
- data/lib/ey_cli/term.rb +58 -0
- data/lib/ey_cli.rb +46 -0
- data/spec/auth_helper.rb +28 -0
- data/spec/ey_cli/api_spec.rb +70 -0
- data/spec/ey_cli/command_manager_spec.rb +33 -0
- data/spec/ey_cli/commands/help_spec.rb +36 -0
- data/spec/ey_cli/controllers/accounts_spec.rb +40 -0
- data/spec/ey_cli/controllers/apps_spec.rb +97 -0
- data/spec/ey_cli/controllers/environments_spec.rb +101 -0
- data/spec/ey_cli/models/app_spec.rb +50 -0
- data/spec/ey_cli/models/base_spec.rb +98 -0
- data/spec/ey_cli/models/environment_spec.rb +51 -0
- data/spec/ey_cli/options_parser_spec.rb +19 -0
- data/spec/ey_cli/smarty_parser_spec.rb +19 -0
- data/spec/spec_helper.rb +29 -0
- metadata +288 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module EYCli
|
2
|
+
module SmartyParser
|
3
|
+
def parse(body, klass = self)
|
4
|
+
case body
|
5
|
+
when Hash
|
6
|
+
klass.new smarty(body)
|
7
|
+
when Array
|
8
|
+
body.map { |item| parse(item, klass) }
|
9
|
+
else
|
10
|
+
body
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def smarty(hash)
|
15
|
+
hash.each do |key, value|
|
16
|
+
case key
|
17
|
+
when /accounts?/
|
18
|
+
hash[key] = parse(value, EYCli::Model::Account)
|
19
|
+
when /apps?/
|
20
|
+
hash[key] = parse(value, EYCli::Model::App)
|
21
|
+
when /environments?/
|
22
|
+
hash[key] = parse(value, EYCli::Model::Environment)
|
23
|
+
else
|
24
|
+
hash[key] = parse(value, Hashie::Mash)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/ey_cli/term.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module EYCli
|
2
|
+
class Term
|
3
|
+
require 'highline'
|
4
|
+
|
5
|
+
attr_reader :terminal
|
6
|
+
|
7
|
+
def initialize(input = $stdin, output = $stdout)
|
8
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
9
|
+
@terminal = HighLine.new(input, output)
|
10
|
+
end
|
11
|
+
|
12
|
+
def choose_resource(collection, message, prompt)
|
13
|
+
say(message)
|
14
|
+
|
15
|
+
terminal.choose do |menu|
|
16
|
+
menu.index = :number
|
17
|
+
menu.index_suffix = ' ~> '
|
18
|
+
menu.prompt = prompt
|
19
|
+
|
20
|
+
collection.each do |resource|
|
21
|
+
menu.choice resource.name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def say(message)
|
27
|
+
terminal.say(message)
|
28
|
+
end
|
29
|
+
|
30
|
+
def error(message)
|
31
|
+
terminal.say(%Q{<%= color("#{message}", :error)%>})
|
32
|
+
end
|
33
|
+
|
34
|
+
def warning(message)
|
35
|
+
terminal.say(%Q{<%= color("#{message}", :warning)%>})
|
36
|
+
end
|
37
|
+
|
38
|
+
def success(message)
|
39
|
+
terminal.say(%Q{<%= color("#{message}", :debug)%>})
|
40
|
+
end
|
41
|
+
|
42
|
+
def print_errors(errors, message)
|
43
|
+
error(message)
|
44
|
+
errors.each do |key, value|
|
45
|
+
alert = value.respond_to?(:join) ? value.join(',') : value.inspect
|
46
|
+
error("\t- #{key}: #{alert}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def ask(prompt, protected_filed = false)
|
51
|
+
if protected_filed
|
52
|
+
terminal.ask(prompt) {|q| q.echo = '*'}
|
53
|
+
else
|
54
|
+
terminal.ask(prompt) {|q| q.readline = true}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/ey_cli.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module EYCli
|
2
|
+
VERSION = '0.1.0'
|
3
|
+
|
4
|
+
require 'hashie/mash'
|
5
|
+
require 'json'
|
6
|
+
require 'multi_json'
|
7
|
+
|
8
|
+
require 'ey_cli/api'
|
9
|
+
require 'ey_cli/cli'
|
10
|
+
require 'ey_cli/git_utils'
|
11
|
+
require 'ey_cli/command_manager'
|
12
|
+
require 'ey_cli/options_parser'
|
13
|
+
require 'ey_cli/smarty_parser'
|
14
|
+
require 'ey_cli/term'
|
15
|
+
|
16
|
+
require 'ey_cli/models/base'
|
17
|
+
require 'ey_cli/models/account'
|
18
|
+
require 'ey_cli/models/app'
|
19
|
+
require 'ey_cli/models/environment'
|
20
|
+
|
21
|
+
require 'ey_cli/controllers/accounts'
|
22
|
+
require 'ey_cli/controllers/apps'
|
23
|
+
require 'ey_cli/controllers/environments'
|
24
|
+
|
25
|
+
require 'ey_cli/commands/base'
|
26
|
+
require 'ey_cli/commands/accounts'
|
27
|
+
require 'ey_cli/commands/apps'
|
28
|
+
require 'ey_cli/commands/console'
|
29
|
+
require 'ey_cli/commands/create_app'
|
30
|
+
require 'ey_cli/commands/create_env'
|
31
|
+
require 'ey_cli/commands/deploy'
|
32
|
+
require 'ey_cli/commands/help'
|
33
|
+
require 'ey_cli/commands/show'
|
34
|
+
|
35
|
+
def self.api(endpoint = nil)
|
36
|
+
@api ||= Api.new(endpoint)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.term(input = $stdin, output = $stdout)
|
40
|
+
@ui ||= Term.new(input, output)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.command_manager
|
44
|
+
@command_manager ||= EYCli::CommandManager.new
|
45
|
+
end
|
46
|
+
end
|
data/spec/auth_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module EYCli
|
2
|
+
module AuthHelper
|
3
|
+
def self.extended(example_group)
|
4
|
+
example_group.use_credentials(example_group)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.included(example_group)
|
8
|
+
example_group.extend self
|
9
|
+
end
|
10
|
+
|
11
|
+
def mock_credentials
|
12
|
+
rc = File.expand_path('../fake_rc', __FILE__)
|
13
|
+
|
14
|
+
File.open(rc, 'w') do |f| f.write <<-EOF
|
15
|
+
---
|
16
|
+
api_token: fake_token
|
17
|
+
EOF
|
18
|
+
end
|
19
|
+
ENV['EYRC'] = rc
|
20
|
+
end
|
21
|
+
|
22
|
+
def use_credentials(describe_block)
|
23
|
+
describe_block.before :each do
|
24
|
+
mock_credentials
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe EYCli::Api do
|
4
|
+
subject { EYCli::Api.new('http://example.com') }
|
5
|
+
|
6
|
+
context "reading the auth token from the file" do
|
7
|
+
it "returns nil if the file doesn't exist" do
|
8
|
+
subject.read_token('fake_file').should be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns nil if the file is empty" do
|
12
|
+
File.open('fake_file', 'w')
|
13
|
+
subject.read_token('fake_file').should be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns the token in the root if there is no token for the endpoint" do
|
17
|
+
File.open('fake_file', 'w') do |f|
|
18
|
+
f.write <<-EOF
|
19
|
+
---
|
20
|
+
api_token: root_api_token
|
21
|
+
EOF
|
22
|
+
end
|
23
|
+
|
24
|
+
subject.read_token('fake_file').should == 'root_api_token'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns the token for the endpoint if exists" do
|
28
|
+
File.open('fake_file', 'w') do |f|
|
29
|
+
f.write <<-EOF
|
30
|
+
---
|
31
|
+
api_token: root_api_token
|
32
|
+
http://example.com:
|
33
|
+
api_token: example_com_api_token
|
34
|
+
EOF
|
35
|
+
end
|
36
|
+
|
37
|
+
subject.read_token('fake_file').should == 'example_com_api_token'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "saving the auth token" do
|
42
|
+
def fake_rc_file
|
43
|
+
File.read('fake_file').gsub(/\s*/m, '')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "stores the token under the enpoint" do
|
47
|
+
subject.save_token('new_token', 'fake_file')
|
48
|
+
fake_rc_file.should == '---http://example.com:api_token:new_token'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "adds it to the file if already existed" do
|
52
|
+
File.open('fake_file', 'w') {|f| f.write("---\n api_token: root_token") }
|
53
|
+
subject.save_token('new_token', 'fake_file')
|
54
|
+
fake_rc_file.should == '---api_token:root_tokenhttp://example.com:api_token:new_token'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "fetching the token from the terminal" do
|
59
|
+
it "sends the user credentials to the api" do
|
60
|
+
EYCli.term.should_receive(:ask).with('Email: ').and_return('foo@foo.com')
|
61
|
+
EYCli.term.should_receive(:ask).with('Password: ', true).and_return('fooooo')
|
62
|
+
|
63
|
+
stub_request(:post, "http://example.com/authenticate?email=foo@foo.com&password=fooooo").
|
64
|
+
to_return(:status => 200, :body => to_json(:api_token => 'foo_token'))
|
65
|
+
|
66
|
+
ENV['EYRC'] = 'fake_file'
|
67
|
+
subject.fetch_token.should == 'foo_token'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module EYCli::Command
|
4
|
+
class MockCommand; end
|
5
|
+
end
|
6
|
+
|
7
|
+
describe EYCli::CommandManager do
|
8
|
+
before { subject.register_command(:mock_command) }
|
9
|
+
|
10
|
+
it "registers commands" do
|
11
|
+
subject.commands.keys.should include(:mock_command)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns nil if the command class is not registered" do
|
15
|
+
subject[:bar].should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns an instance of the command class if it's registered" do
|
19
|
+
subject[:mock_command].should be_instance_of(EYCli::Command::MockCommand)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns nil if the command class is not defined" do
|
23
|
+
subject.register_command(:bar)
|
24
|
+
subject[:bar].should be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "only loads the command class once" do
|
28
|
+
subject.should_receive(:load_command).
|
29
|
+
with(:mock_command).
|
30
|
+
once.and_return(EYCli::Command::MockCommand.new)
|
31
|
+
subject[:mock_command] || subject[:mock_command]
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class EYCli::Command::WithoutHelp; def help; end end
|
4
|
+
class EYCli::Command::WithHelp; def help; 'run with_help' end end
|
5
|
+
|
6
|
+
describe EYCli::Command::Help do
|
7
|
+
before do
|
8
|
+
EYCli.command_manager.register_command :without_help
|
9
|
+
EYCli.command_manager.register_command :with_help
|
10
|
+
end
|
11
|
+
|
12
|
+
it "prints the global help when the command name is not provided" do
|
13
|
+
subject.run([])
|
14
|
+
$stdout_test.string.should =~ /ey_cli help commands/
|
15
|
+
end
|
16
|
+
|
17
|
+
it "says that the help is not available when the command does not exist" do
|
18
|
+
subject.run(['fake_command'])
|
19
|
+
$stdout_test.string.should =~ /help not available/
|
20
|
+
end
|
21
|
+
|
22
|
+
it "says that the help is not available when the command does not have any help message" do
|
23
|
+
subject.run(['without_help'])
|
24
|
+
$stdout_test.string.should =~ /help not available for command: 'without_help'/
|
25
|
+
end
|
26
|
+
|
27
|
+
it "shows the available commands" do
|
28
|
+
subject.run(['commands'])
|
29
|
+
$stdout_test.string.should =~ /available commands/
|
30
|
+
end
|
31
|
+
|
32
|
+
it "shows the help message for the specified command" do
|
33
|
+
subject.run(['with_help'])
|
34
|
+
$stdout_test.string.should =~ /run with_help/
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe EYCli::Controller::Accounts do
|
4
|
+
it "returns the first account if we don't provide a name and the user has only one account" do
|
5
|
+
expected = EYCli::Model::Account.new({:id => 1, :name => 'foo'})
|
6
|
+
stub_request(:get, 'http://example.com/accounts').
|
7
|
+
to_return(:status => 200, :body => to_json({'accounts' => [expected]}))
|
8
|
+
|
9
|
+
account = subject.fetch_account
|
10
|
+
account.should == expected
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns nil if we don't find the account by the name provided" do
|
14
|
+
expected = EYCli::Model::Account.new({:id => 1, :name => 'foo'})
|
15
|
+
stub_request(:get, 'http://example.com/accounts').
|
16
|
+
to_return(:status => 200, :body => to_json({'accounts' => [expected]}))
|
17
|
+
|
18
|
+
subject.fetch_account('bar').should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns nil if the user hasn't created an account yet" do
|
22
|
+
stub_request(:get, 'http://example.com/accounts').
|
23
|
+
to_return(:status => 200, :body => to_json({'accounts' => []}))
|
24
|
+
|
25
|
+
subject.fetch_account.should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns the account selected by the user" do
|
29
|
+
account1 = EYCli::Model::Account.new({:id => 1, :name => 'foo'})
|
30
|
+
account2 = EYCli::Model::Account.new({:id => 2, :name => 'bar'})
|
31
|
+
account3 = EYCli::Model::Account.new({:id => 3, :name => 'baz'})
|
32
|
+
stub_request(:get, 'http://example.com/accounts').
|
33
|
+
to_return(:status => 200, :body => to_json({'accounts' => [account1, account2, account3]}))
|
34
|
+
|
35
|
+
EYCli.term.terminal.should_receive(:choose).and_return('bar')
|
36
|
+
|
37
|
+
account = subject.fetch_account
|
38
|
+
account.should == account2
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe EYCli::Controller::Apps do
|
4
|
+
before { Dir.mkdir('fake_app') }
|
5
|
+
let(:account) { EYCli::Model::Account.new(:id => 1) }
|
6
|
+
|
7
|
+
it "shows an error message when the directory is not a git repository" do
|
8
|
+
EYCli.term.should_receive(:error).with('Not a git repository: fake_app')
|
9
|
+
subject.create(account, 'fake_app')
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'trying to figure out the application type' do
|
13
|
+
it "uses rails 3 as default" do
|
14
|
+
subject.fetch_type('fake_app').should == :rails3
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'is a rails 3 app if the directory has the environment and rackup files' do
|
18
|
+
Dir.mkdir('fake_app/config')
|
19
|
+
['fake_app/config.ru', 'fake_app/config/environment.rb'].each {|f| File.open(f, 'w')}
|
20
|
+
|
21
|
+
subject.fetch_type('fake_app').should == :rails3
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'is a rails 2 app if the directory only includes the environment file' do
|
25
|
+
Dir.mkdir('fake_app/config')
|
26
|
+
File.open('fake_app/config/environment.rb', 'w')
|
27
|
+
subject.fetch_type('fake_app').should == :rails2
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'is a rack app if the directory only includes the rackup file' do
|
31
|
+
File.open('fake_app/config.ru', 'w')
|
32
|
+
subject.fetch_type('fake_app').should == :rack
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'under a git repository' do
|
37
|
+
before { Dir.mkdir('fake_app/.git') }
|
38
|
+
let(:success_params) do
|
39
|
+
{
|
40
|
+
:account => account,
|
41
|
+
'app[name]' => 'fake_app',
|
42
|
+
'app[app_type_id]' => 'rails3',
|
43
|
+
'app[repository_uri]' => 'git@git.com:foo/bar.git'
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'shows an error if the model cannot create the application' do
|
48
|
+
app_with_errors = EYCli::Model::App.new({:errors => {:name => 'bad_name'}})
|
49
|
+
EYCli.term.should_receive(:print_errors).with(app_with_errors.errors, 'App creation failed:')
|
50
|
+
EYCli::Model::App.should_receive(:create).and_return(app_with_errors)
|
51
|
+
|
52
|
+
subject.create(account, 'fake_app')
|
53
|
+
end
|
54
|
+
|
55
|
+
it "shows a success message when the model creates the app" do
|
56
|
+
app = EYCli::Model::App.new({:id => 1, :name => 'fake_app'})
|
57
|
+
EYCli::Model::App.should_receive(:create).with(success_params).and_return(app)
|
58
|
+
EYCli.term.should_receive(:success)
|
59
|
+
subject.should_receive(:fetch_repository).and_return('git@git.com:foo/bar.git')
|
60
|
+
|
61
|
+
subject.create(account, 'fake_app')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context '#fetch_app' do
|
66
|
+
let(:app1) { EYCli::Model::App.new(:id => 1, :repository_uri => 'git@foo.com', :name => 'foo_app') }
|
67
|
+
let(:app2) { EYCli::Model::App.new(:id => 2, :repository_uri => 'git@bar.com', :name => 'bar_app') }
|
68
|
+
|
69
|
+
it 'returns the first app if the user only has one' do
|
70
|
+
stub_request(:get, 'http://example.com/apps').
|
71
|
+
to_return(:status => 200, :body => to_json(:apps => [app1]))
|
72
|
+
subject.fetch_app.should == app1
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns the first app that matches the name passed as an option' do
|
76
|
+
stub_request(:get, 'http://example.com/apps').
|
77
|
+
to_return(:status => 200, :body => to_json(:apps => [app1, app2]))
|
78
|
+
subject.fetch_app(nil, {:app_name => 'bar_app'}).should == app2
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'returns the first app that matches the git repository uri of the base path' do
|
82
|
+
stub_request(:get, 'http://example.com/apps').
|
83
|
+
to_return(:status => 200, :body => to_json(:apps => [app1, app2]))
|
84
|
+
subject.should_receive(:git_repository?).and_return(true)
|
85
|
+
subject.should_receive(:fetch_repository).and_return('git@bar.com')
|
86
|
+
|
87
|
+
subject.fetch_app.should == app2
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'returns the app according to the option the user chooses' do
|
91
|
+
stub_request(:get, 'http://example.com/apps').
|
92
|
+
to_return(:status => 200, :body => to_json(:apps => [app1, app2]))
|
93
|
+
EYCli.term.should_receive(:choose_resource).and_return('bar_app')
|
94
|
+
subject.fetch_app.should == app2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe EYCli::Controller::Environments do
|
4
|
+
let(:app) { EYCli::Model::App.new(:id => 1, :name => 'fake_app') }
|
5
|
+
|
6
|
+
context 'creating a new environment' do
|
7
|
+
let(:success_params) do
|
8
|
+
{
|
9
|
+
:app => app,
|
10
|
+
'environment[name]' => "#{app.name}_production",
|
11
|
+
'environment[framework_env]' => 'production',
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "shows an error message if the model cannot create the environment" do
|
16
|
+
env_with_errors = EYCli::Model::Environment.new({:errors => {:name => 'bad_name'}})
|
17
|
+
EYCli.term.should_receive(:print_errors).with(env_with_errors.errors, 'Environment creation failed:')
|
18
|
+
EYCli::Model::Environment.should_receive(:create).and_return(env_with_errors)
|
19
|
+
|
20
|
+
subject.create(app, {})
|
21
|
+
end
|
22
|
+
|
23
|
+
it "shows a success message when the model creates the app" do
|
24
|
+
env = EYCli::Model::Environment.new({:id => 1, :name => 'fake_app_production', :framework_env => 'production'})
|
25
|
+
EYCli::Model::Environment.should_receive(:create).with(success_params).and_return(env)
|
26
|
+
EYCli.term.should_receive(:success)
|
27
|
+
|
28
|
+
response = subject.create(app, {})
|
29
|
+
response.should == env
|
30
|
+
end
|
31
|
+
|
32
|
+
it "allows to specify the framework environment as a parameter" do
|
33
|
+
params = success_params.merge({'environment[name]' => 'fake_app_staging', 'environment[framework_env]' => 'staging'})
|
34
|
+
env = EYCli::Model::Environment.new({:id => 1, :name => 'fake_app_staging', :framework_env => 'staging'})
|
35
|
+
EYCli::Model::Environment.should_receive(:create).with(params).and_return(env)
|
36
|
+
EYCli.term.should_receive(:success)
|
37
|
+
|
38
|
+
response = subject.create(app, {:framework_env => 'staging'})
|
39
|
+
response.should == env
|
40
|
+
end
|
41
|
+
|
42
|
+
it "allows to specify the environment name" do
|
43
|
+
params = success_params.merge({'environment[name]' => 'fake_environment_name', 'environment[framework_env]' => 'production'})
|
44
|
+
env = EYCli::Model::Environment.new({:id => 1, :name => 'fake_environment_name', :framework_env => 'production'})
|
45
|
+
EYCli::Model::Environment.should_receive(:create).with(params).and_return(env)
|
46
|
+
EYCli.term.should_receive(:success)
|
47
|
+
|
48
|
+
response = subject.create(app, {:name => 'fake_environment_name'})
|
49
|
+
response.should == env
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with cluster options" do
|
53
|
+
it "is pending"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "deploying an environment" do
|
58
|
+
it "shows an error if the application doesn't have any environment" do
|
59
|
+
EYCli.term.should_receive(:error)
|
60
|
+
subject.deploy(app)
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the app has only one environment" do
|
64
|
+
before do
|
65
|
+
@env = mock
|
66
|
+
app[:environments] = [@env]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "uses the environment without asking" do
|
70
|
+
@env.should_receive(:deploy).and_return(Hashie::Mash.new)
|
71
|
+
EYCli.term.should_not_receive(:choose_resource)
|
72
|
+
subject.deploy(app)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "shows the error list when the deploy fails" do
|
76
|
+
expected = Hashie::Mash.new({:errors => {:provision => 'Amazon cannot provision the instance'}})
|
77
|
+
@env.should_receive(:deploy).and_return(expected)
|
78
|
+
EYCli.term.should_receive(:print_errors).with(expected.errors, "Application deployment failed:")
|
79
|
+
subject.deploy(app)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "shows the success message if it doesn't return any error" do
|
83
|
+
@env.should_receive(:deploy).and_return(Hashie::Mash.new)
|
84
|
+
EYCli.term.should_receive(:success)
|
85
|
+
subject.deploy(app)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when the app has more than one environment" do
|
90
|
+
it "shows the environments' list to let the user choose" do
|
91
|
+
env1 = EYCli::Model::Environment.new(:name => 'mock1')
|
92
|
+
env2 = mock
|
93
|
+
env2.should_receive(:name).and_return('mock2')
|
94
|
+
env2.should_receive(:deploy).and_return(Hashie::Mash.new)
|
95
|
+
app[:environments] = [env1, env2]
|
96
|
+
EYCli.term.should_receive(:choose_resource).and_return('mock2')
|
97
|
+
subject.deploy(app)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe EYCli::Model::App do
|
4
|
+
context ".create" do
|
5
|
+
it "return an error if it doesn't find the account" do
|
6
|
+
app = EYCli::Model::App.create({})
|
7
|
+
app.errors?.should be_true
|
8
|
+
app.errors.keys.should include('account')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "return an error if a model validation fails" do
|
12
|
+
account = EYCli::Model::Account.new({:id => 1})
|
13
|
+
stub_request(:post, 'http://example.com/accounts/1/apps?app[name]=foo').
|
14
|
+
to_return(:status => 422, :body => to_json({:errors => {:name => ['App name already exists']}}))
|
15
|
+
|
16
|
+
app = EYCli::Model::App.create({:account => account, 'app[name]' => 'foo'})
|
17
|
+
app.errors?.should be_true
|
18
|
+
app.errors.keys.should include('name')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns the new app when it's successful" do
|
22
|
+
account = EYCli::Model::Account.new({:id => 1})
|
23
|
+
expected = EYCli::Model::App.new({:id => 1, :name => 'foo'})
|
24
|
+
stub_request(:post, 'http://example.com/accounts/1/apps?app[name]=foo').
|
25
|
+
to_return(:status => 201, :body => to_json(:app => expected))
|
26
|
+
|
27
|
+
app = EYCli::Model::App.create({:account => account, 'app[name]' => 'foo'})
|
28
|
+
app.should == expected
|
29
|
+
end
|
30
|
+
|
31
|
+
context '.find_by_repository_uri' do
|
32
|
+
let(:app1) { EYCli::Model::App.new(:id => 1, :repository_uri => 'git@foo.com') }
|
33
|
+
let(:app2) { EYCli::Model::App.new(:id => 2, :repository_uri => 'git@bar.com') }
|
34
|
+
before do
|
35
|
+
stub_request(:get, 'http://example.com/apps').
|
36
|
+
to_return(:status => 200, :body => to_json(:apps => [app1, app2]))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns an instance of App if it finds it" do
|
40
|
+
app = EYCli::Model::App.find_by_repository_uri('git@bar.com')
|
41
|
+
app.should == app2
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns nil when it cannot find the app" do
|
45
|
+
app = EYCli::Model::App.find_by_repository_uri('foo@bar.com')
|
46
|
+
app.should be_nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|