shelly 0.0.30 → 0.0.31

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/lib/shelly/app.rb CHANGED
@@ -50,16 +50,24 @@ module Shelly
50
50
  File.open(cloudfile_path, "a+") { |f| f << content }
51
51
  end
52
52
 
53
- def logs
54
- shelly.cloud_logs(self.code_name)
53
+ def deploy_logs
54
+ shelly.deploy_logs(code_name)
55
+ end
56
+
57
+ def deploy_log(log)
58
+ shelly.deploy_log(code_name, log)
59
+ end
60
+
61
+ def application_logs
62
+ shelly.application_logs(self.code_name)
55
63
  end
56
64
 
57
65
  def start
58
- shelly.start_cloud(self.code_name)
66
+ shelly.start_cloud(code_name)
59
67
  end
60
68
 
61
69
  def stop
62
- shelly.stop_cloud(self.code_name)
70
+ shelly.stop_cloud(code_name)
63
71
  end
64
72
 
65
73
  def cloudfile_path
@@ -71,11 +79,23 @@ module Shelly
71
79
  end
72
80
 
73
81
  def ips
74
- shelly.app_ips(self.code_name)
82
+ shelly.app_ips(code_name)
75
83
  end
76
84
 
77
85
  def users
78
- shelly.app_users(self.code_name)
86
+ shelly.app_users(code_name)
87
+ end
88
+
89
+ def configs
90
+ @configs ||= shelly.app_configs(code_name)
91
+ end
92
+
93
+ def user_configs
94
+ configs.find_all { |config| config["created_by_user"] }
95
+ end
96
+
97
+ def shelly_generated_configs
98
+ configs.find_all { |config| config["created_by_user"] == false }
79
99
  end
80
100
 
81
101
  def open_billing_page
@@ -0,0 +1,47 @@
1
+ require "shelly/cli/command"
2
+
3
+ module Shelly
4
+ module CLI
5
+ class Config < Command
6
+ include Thor::Actions
7
+ include Helpers
8
+
9
+ desc "list", "List configuration files"
10
+ def list
11
+ logged_in?
12
+ say_error "No Cloudfile found" unless Cloudfile.present?
13
+ cloudfile = Cloudfile.new
14
+ cloudfile.clouds.each do |cloud|
15
+ @app = App.new(cloud)
16
+ begin
17
+ configs = @app.configs
18
+ unless configs.empty?
19
+ say "Configuration files for #{cloud}", :green
20
+ user_configs = @app.user_configs
21
+ unless user_configs.empty?
22
+ say "Custom configuration files:"
23
+ user_configs.each { |config| say " * #{config["path"]}" }
24
+ else
25
+ say "You have no custom configuration files."
26
+ end
27
+ shelly_configs = @app.shelly_generated_configs
28
+ unless shelly_configs.empty?
29
+ say "Following files are created by Shelly Cloud:"
30
+ shelly_configs.each { |config| say " * #{config["path"]}" }
31
+ end
32
+ else
33
+ say "Cloud #{cloud} has no configuration files"
34
+ end
35
+ rescue Client::APIError => e
36
+ if e.unauthorized?
37
+ say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
38
+ else
39
+ say_error e.message
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -11,8 +11,8 @@ module Shelly
11
11
  def list(cloud = nil)
12
12
  logged_in?
13
13
  say_error "No Cloudfile found" unless Cloudfile.present?
14
- multiple_clouds(cloud, "deploy list", "Select cloud to view deploy logs using:")
15
- logs = @app.logs
14
+ multiple_clouds(cloud, "deploys list", "Select cloud to view deploy logs using:")
15
+ logs = @app.deploy_logs
16
16
  unless logs.empty?
17
17
  say "Available deploy logs", :green
18
18
  logs.each do |log|
@@ -29,6 +29,47 @@ module Shelly
29
29
  end
30
30
  end
31
31
 
32
+ desc "show LOG", "Show specific deploy log"
33
+ def show(log = nil, cloud = nil)
34
+ say_error "No Cloudfile found" unless Cloudfile.present?
35
+ specify_log(log)
36
+ multiple_clouds(cloud, "deploys show #{log}", "Select log and cloud to view deploy logs using:")
37
+ content = @app.deploy_log(log)
38
+ say "Log for deploy done on #{content["created_at"]}", :green
39
+ if content["bundle_install"]
40
+ say("Starting bundle install", :green); say(content["bundle_install"])
41
+ end
42
+ if content["whenever"]
43
+ say("Starting whenever", :green); say(content["whenever"])
44
+ end
45
+ if content["callbacks"]
46
+ say("Starting callbacks", :green); say(content["callbacks"])
47
+ end
48
+ if content["delayed_job"]
49
+ say("Starting delayed job", :green); say(content["delayed_job"])
50
+ end
51
+ if content["thin_restart"]
52
+ say("Starting thin", :green); say(content["thin_restart"])
53
+ end
54
+ rescue Client::APIError => e
55
+ if e.unauthorized?
56
+ say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
57
+ elsif e.message == "Log not found"
58
+ say_error "Log not found, list all deploy logs using:", :with_exit => false
59
+ say " shelly deploys list #{cloud}"
60
+ exit 1
61
+ end
62
+ end
63
+
64
+ no_tasks do
65
+ def specify_log(log)
66
+ unless log
67
+ say_error "Specify log by passing date value or to see last log use:", :with_exit => false
68
+ say " shelly deploys show last"
69
+ exit 1
70
+ end
71
+ end
72
+ end
32
73
  end
33
74
  end
34
75
  end
@@ -1,6 +1,7 @@
1
1
  require "shelly/cli/command"
2
2
  require "shelly/cli/user"
3
3
  require "shelly/cli/deploys"
4
+ require "shelly/cli/config"
4
5
 
5
6
  module Shelly
6
7
  module CLI
@@ -9,6 +10,7 @@ module Shelly
9
10
  include Helpers
10
11
  register(User, "user", "user <command>", "Manages users using this cloud")
11
12
  register(Deploys, "deploys", "deploys <command>", "View cloud deploy logs")
13
+ register(Config, "config", "config <command>", "Manages cloud configuration files")
12
14
  check_unknown_options!
13
15
 
14
16
  map %w(-v --version) => :version
@@ -234,6 +236,28 @@ module Shelly
234
236
  say_error e.message
235
237
  end
236
238
 
239
+ desc "logs", "Show latest application logs from each instance"
240
+ method_option :cloud, :type => :string, :aliases => "-c",
241
+ :desc => "Specify which cloud to show logs for"
242
+ def logs
243
+ cloud = options[:cloud]
244
+ logged_in?
245
+ say_error "No Cloudfile found" unless Cloudfile.present?
246
+ multiple_clouds(cloud, "logs --cloud", "Select which to show logs for using:")
247
+ begin
248
+ logs = @app.application_logs
249
+ say "Cloud #{@app.code_name}:", :green
250
+ logs.each_with_index do |log, i|
251
+ say "Instance #{i+1}:"
252
+ print_wrapped log, :ident => 2
253
+ end
254
+ rescue Client::APIError => e
255
+ if e.unauthorized?
256
+ say_error "You have no access to cloud '#{cloud || @app.code_name}'"
257
+ end
258
+ end
259
+ end
260
+
237
261
  # FIXME: move to helpers
238
262
  no_tasks do
239
263
  def check_options(options)
data/lib/shelly/client.rb CHANGED
@@ -58,6 +58,10 @@ module Shelly
58
58
  get("/token")
59
59
  end
60
60
 
61
+ def app_configs(cloud)
62
+ get("/apps/#{cloud}/configs")
63
+ end
64
+
61
65
  def send_invitation(cloud, email)
62
66
  post("/apps/#{cloud}/collaborations", :email => email)
63
67
  end
@@ -86,10 +90,18 @@ module Shelly
86
90
  get("/apps")
87
91
  end
88
92
 
89
- def cloud_logs(cloud)
93
+ def deploy_logs(cloud)
90
94
  get("/apps/#{cloud}/deploys")
91
95
  end
92
96
 
97
+ def deploy_log(cloud, log)
98
+ get("/apps/#{cloud}/deploys/#{log}")
99
+ end
100
+
101
+ def application_logs(cloud)
102
+ get("/apps/#{cloud}/logs")
103
+ end
104
+
93
105
  def ssh_key_available?(ssh_key)
94
106
  get("/users/new", :ssh_key => ssh_key)
95
107
  end
@@ -27,6 +27,7 @@ module Shelly
27
27
  end
28
28
  end
29
29
 
30
+ # FIXME: this should return instances of App
30
31
  def clouds
31
32
  @content.keys.sort
32
33
  end
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.0.30"
2
+ VERSION = "0.0.31"
3
3
  end
@@ -48,6 +48,23 @@ describe Shelly::App do
48
48
  end
49
49
  end
50
50
 
51
+ describe "#configs" do
52
+ it "should get configs from client" do
53
+ @client.should_receive(:app_configs).with("foo-staging")
54
+ @app.configs
55
+ end
56
+
57
+ it "should return only user config files" do
58
+ @client.should_receive(:app_configs).with("foo-staging").and_return([])
59
+ @app.user_configs
60
+ end
61
+
62
+ it "should return only shelly genereted config files" do
63
+ @client.should_receive(:app_configs).with("foo-staging").and_return([])
64
+ @app.shelly_generated_configs
65
+ end
66
+ end
67
+
51
68
  describe "#generate_cloudfile" do
52
69
  it "should return generated cloudfile" do
53
70
  user = mock(:email => "bob@example.com")
@@ -128,10 +145,25 @@ config
128
145
  end
129
146
  end
130
147
 
131
- describe "#logs" do
132
- it "should list logs" do
133
- @client.should_receive(:cloud_logs).with("foo-staging")
134
- @app.logs
148
+ describe "#deploy_logs" do
149
+ it "should list deploy_logs" do
150
+ @client.should_receive(:deploy_logs).with("foo-staging")
151
+ @app.deploy_logs
152
+ end
153
+ end
154
+
155
+ describe "#application_logs" do
156
+ it "should list application_logs" do
157
+ @client.should_receive(:application_logs).with("foo-staging").
158
+ and_return({"logs" => ["log1", "log2"]})
159
+ @app.application_logs
160
+ end
161
+ end
162
+
163
+ describe "#deploy_log" do
164
+ it "should show log" do
165
+ @client.should_receive(:deploy_log).with("foo-staging", "2011-11-29-11-50-16")
166
+ @app.deploy_log("2011-11-29-11-50-16")
135
167
  end
136
168
  end
137
169
 
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+ require "shelly/cli/config"
3
+
4
+ describe Shelly::CLI::Config do
5
+
6
+ before do
7
+ FileUtils.stub(:chmod)
8
+ @config = Shelly::CLI::Config.new
9
+ @client = mock
10
+ Shelly::Client.stub(:new).and_return(@client)
11
+ $stdout.stub(:puts)
12
+ $stdout.stub(:print)
13
+ end
14
+
15
+ describe "#list" do
16
+ before do
17
+ FileUtils.mkdir_p("/projects/foo")
18
+ Dir.chdir("/projects/foo")
19
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
20
+ @client.stub(:token).and_return("abc")
21
+ end
22
+
23
+ it "should exit with message if there is no Cloudfile" do
24
+ File.delete("Cloudfile")
25
+ $stdout.should_receive(:puts).with(red "No Cloudfile found")
26
+ lambda {
27
+ @config.list
28
+ }.should raise_error(SystemExit)
29
+ end
30
+
31
+ it "should exit if user doesn't have access to cloud in Cloudfile" do
32
+ response = {"message" => "Cloud foo-staging not found"}
33
+ exception = Shelly::Client::APIError.new(response.to_json)
34
+ @client.stub(:app_configs).and_raise(exception)
35
+ $stdout.should_receive(:puts).with(red "You have no access to 'foo-production' cloud defined in Cloudfile")
36
+ lambda { @config.list }.should raise_error(SystemExit)
37
+ end
38
+
39
+ it "should list available configuration files for clouds" do
40
+ @client.should_receive(:app_configs).with("foo-staging").and_return([{"created_by_user" => true, "path" => "config/settings.yml"}])
41
+ @client.should_receive(:app_configs).with("foo-production").and_return([{"created_by_user" => false, "path" => "config/app.yml"}])
42
+ $stdout.should_receive(:puts).with(green "Configuration files for foo-production")
43
+ $stdout.should_receive(:puts).with("You have no custom configuration files.")
44
+ $stdout.should_receive(:puts).with("Following files are created by Shelly Cloud:")
45
+ $stdout.should_receive(:puts).with(" * config/app.yml")
46
+ $stdout.should_receive(:puts).with(green "Configuration files for foo-staging")
47
+ $stdout.should_receive(:puts).with("Custom configuration files:")
48
+ $stdout.should_receive(:puts).with(" * config/settings.yml")
49
+
50
+ @config.list
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -30,7 +30,7 @@ describe Shelly::CLI::Deploys do
30
30
  it "should exit if user doesn't have access to cloud in Cloudfile" do
31
31
  response = {"message" => "Cloud foo-staging not found"}
32
32
  exception = Shelly::Client::APIError.new(response.to_json)
33
- @client.stub(:cloud_logs).and_raise(exception)
33
+ @client.stub(:deploy_logs).and_raise(exception)
34
34
  $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
35
35
  lambda { @deploys.list }.should raise_error(SystemExit)
36
36
  end
@@ -42,7 +42,7 @@ describe Shelly::CLI::Deploys do
42
42
 
43
43
  it "should show information to select specific cloud and exit" do
44
44
  $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select cloud to view deploy logs using:")
45
- $stdout.should_receive(:puts).with(" shelly deploy list foo-production")
45
+ $stdout.should_receive(:puts).with(" shelly deploys list foo-production")
46
46
  $stdout.should_receive(:puts).with("Available clouds:")
47
47
  $stdout.should_receive(:puts).with(" * foo-production")
48
48
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -50,7 +50,7 @@ describe Shelly::CLI::Deploys do
50
50
  end
51
51
 
52
52
  it "should take cloud from command line for which to show logs" do
53
- @client.should_receive(:cloud_logs).with("foo-staging").and_return([{"failed" => false, "created_at" => "2011-12-12-14-14-59"}])
53
+ @client.should_receive(:deploy_logs).with("foo-staging").and_return([{"failed" => false, "created_at" => "2011-12-12-14-14-59"}])
54
54
  $stdout.should_receive(:puts).with(green "Available deploy logs")
55
55
  $stdout.should_receive(:puts).with(" * 2011-12-12-14-14-59")
56
56
  @deploys.list("foo-staging")
@@ -59,15 +59,88 @@ describe Shelly::CLI::Deploys do
59
59
 
60
60
  context "single cloud" do
61
61
  it "should display available logs" do
62
- @client.should_receive(:cloud_logs).with("foo-staging").and_return([{"failed" => false, "created_at" => "2011-12-12-14-14-59"}, {"failed" => true, "created_at" => "2011-12-12-15-14-59"}])
62
+ @client.should_receive(:deploy_logs).with("foo-staging").and_return([{"failed" => false, "created_at" => "2011-12-12-14-14-59"}, {"failed" => true, "created_at" => "2011-12-12-15-14-59"}])
63
63
  $stdout.should_receive(:puts).with(green "Available deploy logs")
64
64
  $stdout.should_receive(:puts).with(" * 2011-12-12-14-14-59")
65
65
  $stdout.should_receive(:puts).with(" * 2011-12-12-15-14-59 (failed)")
66
66
  @deploys.list
67
67
  end
68
+ end
69
+ end
70
+
71
+ describe "#show" do
72
+ before do
73
+ FileUtils.mkdir_p("/projects/foo")
74
+ Dir.chdir("/projects/foo")
75
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\n") }
76
+ @client.stub(:token).and_return("abc")
77
+ end
78
+
79
+ it "should exit with message if there is no Cloudfile" do
80
+ File.delete("Cloudfile")
81
+ $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m")
82
+ lambda {
83
+ @deploys.show
84
+ }.should raise_error(SystemExit)
85
+ end
86
+
87
+ it "should exit if user doesn't have access to cloud in Cloudfile" do
88
+ response = {"message" => "Cloud foo-staging not found"}
89
+ exception = Shelly::Client::APIError.new(response.to_json)
90
+ @client.stub(:deploy_log).and_raise(exception)
91
+ $stdout.should_receive(:puts).with(red "You have no access to 'foo-staging' cloud defined in Cloudfile")
92
+ lambda { @deploys.show("last") }.should raise_error(SystemExit)
93
+ end
94
+
95
+ context "multiple clouds" do
96
+ before do
97
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
98
+ end
99
+
100
+ it "should show information to select specific cloud and exit" do
101
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select log and cloud to view deploy logs using:")
102
+ $stdout.should_receive(:puts).with(" shelly deploys show last foo-production")
103
+ $stdout.should_receive(:puts).with("Available clouds:")
104
+ $stdout.should_receive(:puts).with(" * foo-production")
105
+ $stdout.should_receive(:puts).with(" * foo-staging")
106
+ lambda { @deploys.show("last") }.should raise_error(SystemExit)
107
+ end
108
+
109
+ it "should render the logs" do
110
+ @client.should_receive(:deploy_log).with("foo-staging", "last").and_return(response)
111
+ expected_output
112
+ @deploys.show("last", "foo-staging")
113
+ end
114
+ end
115
+
116
+ context "single cloud" do
117
+ it "should render logs without passing cloud" do
118
+ @client.should_receive(:deploy_log).with("foo-staging", "last").and_return(response)
119
+ expected_output
120
+ @deploys.show("last")
121
+ end
122
+ end
123
+
124
+ def expected_output
125
+ $stdout.should_receive(:puts).with(green "Log for deploy done on 2011-12-12 at 14:14:59")
126
+ $stdout.should_receive(:puts).with(green "Starting bundle install")
127
+ $stdout.should_receive(:puts).with("Installing gems")
128
+ $stdout.should_receive(:puts).with(green "Starting whenever")
129
+ $stdout.should_receive(:puts).with("Looking up schedule.rb")
130
+ $stdout.should_receive(:puts).with(green "Starting callbacks")
131
+ $stdout.should_receive(:puts).with("rake db:migrate")
132
+ $stdout.should_receive(:puts).with(green "Starting delayed job")
133
+ $stdout.should_receive(:puts).with("delayed jobs")
134
+ $stdout.should_receive(:puts).with(green "Starting thin")
135
+ $stdout.should_receive(:puts).with("thins up and running")
136
+ end
68
137
 
138
+ def response
139
+ {"created_at" => "2011-12-12 at 14:14:59", "bundle_install" => "Installing gems",
140
+ "whenever" => "Looking up schedule.rb", "thin_restart" => "thins up and running",
141
+ "delayed_job" => "delayed jobs", "callbacks" => "rake db:migrate"}
69
142
  end
70
143
 
71
144
  end
72
145
 
73
- end
146
+ end
@@ -24,12 +24,14 @@ describe Shelly::CLI::Main do
24
24
  expected = <<-OUT
25
25
  Tasks:
26
26
  shelly add # Adds new cloud to Shelly Cloud
27
+ shelly config <command> # Manages cloud configuration files
27
28
  shelly delete CODE-NAME # Delete cloud from Shelly Cloud
28
29
  shelly deploys <command> # View cloud deploy logs
29
30
  shelly help [TASK] # Describe available tasks or one specific task
30
31
  shelly ip # Lists clouds IP's
31
32
  shelly list # Lists all your clouds
32
33
  shelly login [EMAIL] # Logs user in to Shelly Cloud
34
+ shelly logs # Show latest application logs from each instance
33
35
  shelly register [EMAIL] # Registers new user account on Shelly Cloud
34
36
  shelly start [CODE-NAME] # Starts specific cloud
35
37
  shelly stop [CODE-NAME] # Stops specific cloud
@@ -42,6 +44,21 @@ OUT
42
44
  out = IO.popen("bin/shelly").read.strip
43
45
  out.should == expected.strip
44
46
  end
47
+
48
+ it "should display options in help for logs" do
49
+ expected = <<-OUT
50
+ Usage:
51
+ shelly logs
52
+
53
+ Options:
54
+ -c, [--cloud=CLOUD] # Specify which cloud to show logs for
55
+ [--debug] # Show debug information
56
+
57
+ Show latest application logs from each instance
58
+ OUT
59
+ out = IO.popen("bin/shelly help logs").read.strip
60
+ out.should == expected.strip
61
+ end
45
62
  end
46
63
 
47
64
  describe "#register" do
@@ -775,4 +792,95 @@ OUT
775
792
  end
776
793
  end
777
794
  end
795
+
796
+ describe "#logs" do
797
+ before do
798
+ @user = Shelly::User.new
799
+ @client.stub(:token).and_return("abc")
800
+ FileUtils.mkdir_p("/projects/foo")
801
+ Dir.chdir("/projects/foo")
802
+ File.open("Cloudfile", 'w') {|f| f.write("foo-production:\n") }
803
+ Shelly::User.stub(:new).and_return(@user)
804
+ @client.stub(:apps).and_return([{"code_name" => "foo-production"},
805
+ {"code_name" => "foo-staging"}])
806
+ @app = Shelly::App.new
807
+ Shelly::App.stub(:new).and_return(@app)
808
+ end
809
+
810
+ it "should exit if there is no Cloudfile" do
811
+ File.delete("Cloudfile")
812
+ $stdout.should_receive(:puts).with("\e[31mNo Cloudfile found\e[0m")
813
+ lambda {
814
+ @main.logs
815
+ }.should raise_error(SystemExit)
816
+ end
817
+
818
+ it "should exit if user doesn't have access to clouds in Cloudfile" do
819
+ response = {"message" => "Cloud foo-production not found"}
820
+ exception = Shelly::Client::APIError.new(response.to_json)
821
+ @client.stub(:application_logs).and_raise(exception)
822
+ $stdout.should_receive(:puts).
823
+ with(red "You have no access to cloud 'foo-production'")
824
+ lambda { @main.logs }.should raise_error(SystemExit)
825
+ end
826
+
827
+ it "should exit if user is not logged in" do
828
+ response = {"message" => "Unauthorized"}
829
+ exception = Shelly::Client::APIError.new(response.to_json)
830
+ @client.stub(:token).and_raise(exception)
831
+ $stdout.should_receive(:puts).
832
+ with(red "You are not logged in. To log in use:")
833
+ $stdout.should_receive(:puts).with(" shelly login")
834
+ lambda { @main.logs }.should raise_error(SystemExit)
835
+ end
836
+
837
+ context "single cloud in Cloudfile" do
838
+ it "should show logs for the cloud" do
839
+ @client.stub(:application_logs).and_return(["log1"])
840
+ $stdout.should_receive(:puts).with(green "Cloud foo-production:")
841
+ $stdout.should_receive(:puts).with("Instance 1:")
842
+ $stdout.should_receive(:puts).with(" log1")
843
+ @main.logs
844
+ end
845
+ end
846
+
847
+ context "multiple clouds in Cloudfile" do
848
+ before do
849
+ File.open("Cloudfile", 'w') {|f|
850
+ f.write("foo-staging:\nfoo-production:\n") }
851
+ end
852
+
853
+ it "should show information to print logs for specific cloud and exit" do
854
+ $stdout.should_receive(:puts).
855
+ with("You have multiple clouds in Cloudfile. Select which to show logs for using:")
856
+ $stdout.should_receive(:puts).with(" shelly logs --cloud foo-production")
857
+ $stdout.should_receive(:puts).with("Available clouds:")
858
+ $stdout.should_receive(:puts).with(" * foo-production")
859
+ $stdout.should_receive(:puts).with(" * foo-staging")
860
+ lambda { @main.logs }.should raise_error(SystemExit)
861
+ end
862
+
863
+ it "should fetch from command line which cloud to start" do
864
+ @client.should_receive(:application_logs).with("foo-staging").
865
+ and_return(["log1"])
866
+ $stdout.should_receive(:puts).with(green "Cloud foo-staging:")
867
+ $stdout.should_receive(:puts).with("Instance 1:")
868
+ $stdout.should_receive(:puts).with(" log1")
869
+ @main.options = {:cloud => "foo-staging"}
870
+ @main.logs
871
+ end
872
+ end
873
+
874
+ context "multiple instances" do
875
+ it "should show logs from each instance" do
876
+ @client.stub(:application_logs).and_return(["log1", "log2"])
877
+ $stdout.should_receive(:puts).with(green "Cloud foo-production:")
878
+ $stdout.should_receive(:puts).with("Instance 1:")
879
+ $stdout.should_receive(:puts).with(" log1")
880
+ $stdout.should_receive(:puts).with("Instance 2:")
881
+ $stdout.should_receive(:puts).with(" log2")
882
+ @main.logs
883
+ end
884
+ end
885
+ end
778
886
  end
@@ -100,17 +100,43 @@ describe Shelly::Client do
100
100
  end
101
101
  end
102
102
 
103
- describe "#cloud_logs" do
103
+ describe "#deploy_logs" do
104
104
  it "should send get request" do
105
105
  time = Time.now
106
106
  FakeWeb.register_uri(:get, @url + "/apps/staging-foo/deploys", :body => [{:failed => false, :created_at => time},
107
107
  {:failed => true, :created_at => time+1}].to_json)
108
- response = @client.cloud_logs("staging-foo")
108
+ response = @client.deploy_logs("staging-foo")
109
109
  response.should == [{"failed"=>false, "created_at"=>time.to_s},
110
110
  {"failed"=>true, "created_at"=>(time+1).to_s}]
111
111
  end
112
112
  end
113
113
 
114
+ describe "#deploy_log" do
115
+ it "should send get request with cloud and log" do
116
+ FakeWeb.register_uri(:get, @url + "/apps/staging-foo/deploys/2011-11-29-11-50-16", :body => {:content => "Log"}.to_json)
117
+ response = @client.deploy_log("staging-foo", "2011-11-29-11-50-16")
118
+ response.should == {"content" => "Log"}
119
+ end
120
+ end
121
+
122
+ describe "#app_configs" do
123
+ it "should send get request" do
124
+ FakeWeb.register_uri(:get, @url + "/apps/staging-foo/configs", :body => [{:created_by_user => true, :path => "config/app.yml"}].to_json)
125
+ response = @client.app_configs("staging-foo")
126
+ response.should == [{"created_by_user" => true, "path" => "config/app.yml"}]
127
+ end
128
+ end
129
+
130
+ describe "#application_logs" do
131
+ it "should send get request" do
132
+ time = Time.now
133
+ FakeWeb.register_uri(:get, @url + "/apps/staging-foo/logs",
134
+ :body => {:logs => ["application_log_1", "application_log_2"]}.to_json)
135
+ response = @client.application_logs("staging-foo")
136
+ response.should == {"logs" => ["application_log_1", "application_log_2"]}
137
+ end
138
+ end
139
+
114
140
  describe "#create_app" do
115
141
  it "should send post with app's attributes" do
116
142
  @client.should_receive(:post).with("/apps", :app => {:code_name => "foo", :ruby_version => "1.9.2"})
metadata CHANGED
@@ -1,156 +1,202 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.30
3
+ version: !ruby/object:Gem::Version
4
+ hash: 33
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 31
10
+ version: 0.0.31
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Shelly Cloud team
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2011-12-19 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2011-12-19 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: rspec
16
- requirement: &70153945354720 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
22
32
  type: :development
23
- prerelease: false
24
- version_requirements: *70153945354720
25
- - !ruby/object:Gem::Dependency
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
26
35
  name: rake
27
- requirement: &70153945354300 !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
28
38
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '0'
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
33
46
  type: :development
34
- prerelease: false
35
- version_requirements: *70153945354300
36
- - !ruby/object:Gem::Dependency
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
37
49
  name: guard
38
- requirement: &70153945353880 !ruby/object:Gem::Requirement
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
39
52
  none: false
40
- requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
43
- version: '0'
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
44
60
  type: :development
45
- prerelease: false
46
- version_requirements: *70153945353880
47
- - !ruby/object:Gem::Dependency
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
48
63
  name: guard-rspec
49
- requirement: &70153945353460 !ruby/object:Gem::Requirement
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
50
66
  none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
55
74
  type: :development
56
- prerelease: false
57
- version_requirements: *70153945353460
58
- - !ruby/object:Gem::Dependency
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
59
77
  name: growl_notify
60
- requirement: &70153945353000 !ruby/object:Gem::Requirement
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
61
80
  none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
66
88
  type: :development
67
- prerelease: false
68
- version_requirements: *70153945353000
69
- - !ruby/object:Gem::Dependency
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
70
91
  name: rb-fsevent
71
- requirement: &70153945352580 !ruby/object:Gem::Requirement
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
72
94
  none: false
73
- requirements:
74
- - - ! '>='
75
- - !ruby/object:Gem::Version
76
- version: '0'
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
77
102
  type: :development
78
- prerelease: false
79
- version_requirements: *70153945352580
80
- - !ruby/object:Gem::Dependency
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
81
105
  name: fakefs
82
- requirement: &70153945352160 !ruby/object:Gem::Requirement
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
83
108
  none: false
84
- requirements:
85
- - - ! '>='
86
- - !ruby/object:Gem::Version
87
- version: '0'
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ hash: 3
113
+ segments:
114
+ - 0
115
+ version: "0"
88
116
  type: :development
89
- prerelease: false
90
- version_requirements: *70153945352160
91
- - !ruby/object:Gem::Dependency
117
+ version_requirements: *id007
118
+ - !ruby/object:Gem::Dependency
92
119
  name: fakeweb
93
- requirement: &70153945351740 !ruby/object:Gem::Requirement
120
+ prerelease: false
121
+ requirement: &id008 !ruby/object:Gem::Requirement
94
122
  none: false
95
- requirements:
96
- - - ! '>='
97
- - !ruby/object:Gem::Version
98
- version: '0'
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
99
130
  type: :development
100
- prerelease: false
101
- version_requirements: *70153945351740
102
- - !ruby/object:Gem::Dependency
131
+ version_requirements: *id008
132
+ - !ruby/object:Gem::Dependency
103
133
  name: wijet-thor
104
- requirement: &70153945351240 !ruby/object:Gem::Requirement
134
+ prerelease: false
135
+ requirement: &id009 !ruby/object:Gem::Requirement
105
136
  none: false
106
- requirements:
137
+ requirements:
107
138
  - - ~>
108
- - !ruby/object:Gem::Version
139
+ - !ruby/object:Gem::Version
140
+ hash: 41
141
+ segments:
142
+ - 0
143
+ - 14
144
+ - 7
109
145
  version: 0.14.7
110
146
  type: :runtime
111
- prerelease: false
112
- version_requirements: *70153945351240
113
- - !ruby/object:Gem::Dependency
147
+ version_requirements: *id009
148
+ - !ruby/object:Gem::Dependency
114
149
  name: rest-client
115
- requirement: &70153945350820 !ruby/object:Gem::Requirement
150
+ prerelease: false
151
+ requirement: &id010 !ruby/object:Gem::Requirement
116
152
  none: false
117
- requirements:
118
- - - ! '>='
119
- - !ruby/object:Gem::Version
120
- version: '0'
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ hash: 3
157
+ segments:
158
+ - 0
159
+ version: "0"
121
160
  type: :runtime
122
- prerelease: false
123
- version_requirements: *70153945350820
124
- - !ruby/object:Gem::Dependency
161
+ version_requirements: *id010
162
+ - !ruby/object:Gem::Dependency
125
163
  name: json
126
- requirement: &70153945350280 !ruby/object:Gem::Requirement
164
+ prerelease: false
165
+ requirement: &id011 !ruby/object:Gem::Requirement
127
166
  none: false
128
- requirements:
129
- - - ! '>='
130
- - !ruby/object:Gem::Version
131
- version: '0'
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ hash: 3
171
+ segments:
172
+ - 0
173
+ version: "0"
132
174
  type: :runtime
133
- prerelease: false
134
- version_requirements: *70153945350280
135
- - !ruby/object:Gem::Dependency
175
+ version_requirements: *id011
176
+ - !ruby/object:Gem::Dependency
136
177
  name: wijet-launchy
137
- requirement: &70153945365700 !ruby/object:Gem::Requirement
178
+ prerelease: false
179
+ requirement: &id012 !ruby/object:Gem::Requirement
138
180
  none: false
139
- requirements:
140
- - - ! '>='
141
- - !ruby/object:Gem::Version
142
- version: '0'
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ hash: 3
185
+ segments:
186
+ - 0
187
+ version: "0"
143
188
  type: :runtime
144
- prerelease: false
145
- version_requirements: *70153945365700
189
+ version_requirements: *id012
146
190
  description: Tool for managing applications and clouds at shellycloud.com
147
- email:
191
+ email:
148
192
  - support@shellycloud.com
149
- executables:
193
+ executables:
150
194
  - shelly
151
195
  extensions: []
196
+
152
197
  extra_rdoc_files: []
153
- files:
198
+
199
+ files:
154
200
  - .gitignore
155
201
  - .travis.yml
156
202
  - Gemfile
@@ -163,6 +209,7 @@ files:
163
209
  - lib/shelly.rb
164
210
  - lib/shelly/app.rb
165
211
  - lib/shelly/cli/command.rb
212
+ - lib/shelly/cli/config.rb
166
213
  - lib/shelly/cli/deploys.rb
167
214
  - lib/shelly/cli/main.rb
168
215
  - lib/shelly/cli/runner.rb
@@ -181,6 +228,7 @@ files:
181
228
  - spec/helpers.rb
182
229
  - spec/input_faker.rb
183
230
  - spec/shelly/app_spec.rb
231
+ - spec/shelly/cli/config_spec.rb
184
232
  - spec/shelly/cli/deploys_spec.rb
185
233
  - spec/shelly/cli/main_spec.rb
186
234
  - spec/shelly/cli/runner_spec.rb
@@ -193,32 +241,42 @@ files:
193
241
  - spec/thor/options_spec.rb
194
242
  homepage: http://shellycloud.com
195
243
  licenses: []
244
+
196
245
  post_install_message:
197
246
  rdoc_options: []
198
- require_paths:
247
+
248
+ require_paths:
199
249
  - lib
200
- required_ruby_version: !ruby/object:Gem::Requirement
250
+ required_ruby_version: !ruby/object:Gem::Requirement
201
251
  none: false
202
- requirements:
203
- - - ! '>='
204
- - !ruby/object:Gem::Version
205
- version: '0'
206
- required_rubygems_version: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - ">="
254
+ - !ruby/object:Gem::Version
255
+ hash: 3
256
+ segments:
257
+ - 0
258
+ version: "0"
259
+ required_rubygems_version: !ruby/object:Gem::Requirement
207
260
  none: false
208
- requirements:
209
- - - ! '>='
210
- - !ruby/object:Gem::Version
211
- version: '0'
261
+ requirements:
262
+ - - ">="
263
+ - !ruby/object:Gem::Version
264
+ hash: 3
265
+ segments:
266
+ - 0
267
+ version: "0"
212
268
  requirements: []
269
+
213
270
  rubyforge_project: shelly
214
271
  rubygems_version: 1.8.10
215
272
  signing_key:
216
273
  specification_version: 3
217
274
  summary: Shelly Cloud command line tool
218
- test_files:
275
+ test_files:
219
276
  - spec/helpers.rb
220
277
  - spec/input_faker.rb
221
278
  - spec/shelly/app_spec.rb
279
+ - spec/shelly/cli/config_spec.rb
222
280
  - spec/shelly/cli/deploys_spec.rb
223
281
  - spec/shelly/cli/main_spec.rb
224
282
  - spec/shelly/cli/runner_spec.rb