shelly 0.0.32 → 0.0.33

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  *.gem
2
2
  .bundle
3
+ .tmp.swp
3
4
  Gemfile.lock
4
5
  pkg/*
5
6
  .rvmrc
data/lib/shelly/app.rb CHANGED
@@ -106,6 +106,22 @@ module Shelly
106
106
  configs.find_all { |config| config["created_by_user"] == false }
107
107
  end
108
108
 
109
+ def config(id)
110
+ shelly.app_config(code_name, id)
111
+ end
112
+
113
+ def create_config(path, content)
114
+ shelly.app_create_config(code_name, path, content)
115
+ end
116
+
117
+ def update_config(id, content)
118
+ shelly.app_update_config(code_name, id, content)
119
+ end
120
+
121
+ def delete_config(id)
122
+ shelly.app_delete_config(code_name, id)
123
+ end
124
+
109
125
  def open_billing_page
110
126
  url = "#{shelly.shellyapp_url}/login?api_key=#{current_user.token}&return_to=/apps/#{code_name}/edit_billing"
111
127
  Launchy.open(url)
@@ -6,12 +6,14 @@ module Shelly
6
6
  namespace :backup
7
7
  include Helpers
8
8
 
9
- desc "list", "List database backup clouds defined in Cloudfile"
10
- def list(cloud = nil)
9
+ desc "list", "List database backups"
10
+ method_option :cloud, :type => :string, :aliases => "-c",
11
+ :desc => "Specify which cloud to list backups for"
12
+ def list
11
13
  logged_in?
12
14
  say_error "Must be run inside your project git repository" unless App.inside_git_repository?
13
15
  say_error "No Cloudfile found" unless Cloudfile.present?
14
- multiple_clouds(cloud, "backup list", "Select cloud to view database backups using:")
16
+ multiple_clouds(options[:cloud], "backup list", "Select cloud to view database backups for using:")
15
17
  backups = @app.database_backups
16
18
  unless backups.empty?
17
19
  backups.unshift({"filename" => "Filename", "size" => "Size"})
@@ -20,14 +20,14 @@ module Shelly
20
20
  user_configs = @app.user_configs
21
21
  unless user_configs.empty?
22
22
  say "Custom configuration files:"
23
- user_configs.each { |config| say " * #{config["path"]}" }
23
+ print_configs(user_configs)
24
24
  else
25
25
  say "You have no custom configuration files."
26
26
  end
27
27
  shelly_configs = @app.shelly_generated_configs
28
28
  unless shelly_configs.empty?
29
29
  say "Following files are created by Shelly Cloud:"
30
- shelly_configs.each { |config| say " * #{config["path"]}" }
30
+ print_configs(shelly_configs)
31
31
  end
32
32
  else
33
33
  say "Cloud #{cloud} has no configuration files"
@@ -42,6 +42,121 @@ module Shelly
42
42
  end
43
43
  end
44
44
 
45
+ method_option :cloud, :type => :string, :aliases => "-c",
46
+ :desc => "Specify which cloud to show configuration file for"
47
+ desc "show CONFIG_ID", "View configuration file"
48
+ def show(id = nil)
49
+ logged_in?
50
+ say_error "No Cloudfile found" unless Cloudfile.present?
51
+ say_error "No configuration file specified" unless id
52
+ multiple_clouds(options[:cloud], "show #{id}", "Specify cloud using:")
53
+ config = @app.config(id)
54
+ say "Content of #{config["path"]}:", :green
55
+ say config["content"]
56
+ end
57
+
58
+ map "new" => :create
59
+ method_option :cloud, :type => :string, :aliases => "-c",
60
+ :desc => "Specify for which cloud create configuration file"
61
+ desc "create PATH", "Create configuration file"
62
+ def create(path = nil)
63
+ logged_in?
64
+ say_error "No Cloudfile found" unless Cloudfile.present?
65
+ say_error "No path specified" unless path
66
+ output = open_editor(path)
67
+ multiple_clouds(options[:cloud], "create #{path}", "Specify cloud using:")
68
+ @app.create_config(path, output)
69
+ say "File '#{path}' created, it will be used after next code deploy", :green
70
+ rescue Client::APIError => e
71
+ if e.unauthorized?
72
+ say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
73
+ elsif e.validation?
74
+ e.each_error { |error| say_error error, :with_exit => false }
75
+ exit 1
76
+ else
77
+ say_error e.message
78
+ end
79
+ end
80
+
81
+ map "update" => :edit
82
+ method_option :cloud, :type => :string, :aliases => "-c",
83
+ :desc => "Specify for which cloud edit configuration file"
84
+ desc "edit CONFIG_ID", "Edit configuration file"
85
+ def edit(id = nil)
86
+ logged_in?
87
+ say_error "No Cloudfile found" unless Cloudfile.present?
88
+ say_error "No configuration file specified" unless id
89
+ multiple_clouds(options[:cloud], "edit #{id}", "Specify cloud using:")
90
+ config = @app.config(id)
91
+ content = open_editor(config["path"], config["content"])
92
+ @app.update_config(id, content)
93
+ say "File '#{config["path"]}' updated, it will be used after next code deploy", :green
94
+ rescue Client::APIError => e
95
+ if e.unauthorized?
96
+ say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
97
+ elsif e.validation?
98
+ e.each_error { |error| say_error error, :with_exit => false }
99
+ exit 1
100
+ else
101
+ say_error e.message
102
+ end
103
+ end
104
+
105
+ method_option :cloud, :type => :string, :aliases => "-c",
106
+ :desc => "Specify for which cloud delete configuration file"
107
+ desc "delete CONFIG_ID", "Delete configuration file"
108
+ def delete(id = nil)
109
+ logged_in?
110
+ say_error "No Cloudfile found" unless Cloudfile.present?
111
+ say_error "No configuration file specified" unless id
112
+ multiple_clouds(options[:cloud], "delete #{id}", "Specify cloud using:")
113
+ config = @app.config(id)
114
+ answer = ask("Are you sure you want to delete '#{config["path"]}' [y/n]: ")
115
+ if answer =~ /yes|YES|y|Y/
116
+ @app.delete_config(id)
117
+ say "File deleted, redeploy your cloud to make changes", :green
118
+ else
119
+ say "File not deleted"
120
+ end
121
+ rescue Client::APIError => e
122
+ if e.unauthorized?
123
+ say_error "You have no access to '#{@app.code_name}' cloud defined in Cloudfile"
124
+ elsif e.validation?
125
+ e.each_error { |error| say_error error, :with_exit => false }
126
+ exit 1
127
+ else
128
+ say_error e.message
129
+ end
130
+ end
131
+
132
+ no_tasks do
133
+ def print_configs(configs)
134
+ print_table(configs.map { |config|
135
+ [" * ", config["id"], config["path"]] })
136
+ end
137
+
138
+ def open_editor(path, output = "")
139
+ filename = "shelly-edit-"
140
+ 0.upto(20) { filename += rand(9).to_s }
141
+ filename << File.extname(path)
142
+ filename = File.join(Dir.tmpdir, filename)
143
+ tf = File.open(filename, "w")
144
+ tf.sync = true
145
+ tf.puts output
146
+ tf.close
147
+ no_editor unless system("#{ENV['EDITOR']} #{tf.path}")
148
+ tf = File.open(filename, "r")
149
+ output = tf.gets(nil)
150
+ tf.close
151
+ File.unlink(filename)
152
+ output
153
+ end
154
+
155
+ def no_editor
156
+ say_error "Please set EDITOR environment variable"
157
+ end
158
+ end
159
+
45
160
  end
46
161
  end
47
162
  end
@@ -8,10 +8,12 @@ module Shelly
8
8
  include Helpers
9
9
 
10
10
  desc "list", "Lists deploy logs"
11
- def list(cloud = nil)
11
+ method_option :cloud, :type => :string, :aliases => "-c",
12
+ :desc => "Specify which cloud to show deploy logs for"
13
+ def list
12
14
  logged_in?
13
15
  say_error "No Cloudfile found" unless Cloudfile.present?
14
- multiple_clouds(cloud, "deploys list", "Select cloud to view deploy logs using:")
16
+ multiple_clouds(options[:cloud], "deploys list", "Select cloud to view deploy logs using:")
15
17
  logs = @app.deploy_logs
16
18
  unless logs.empty?
17
19
  say "Available deploy logs", :green
@@ -30,10 +32,12 @@ module Shelly
30
32
  end
31
33
 
32
34
  desc "show LOG", "Show specific deploy log"
33
- def show(log = nil, cloud = nil)
35
+ method_option :cloud, :type => :string, :aliases => "-c",
36
+ :desc => "Specify which cloud to show deploy logs for"
37
+ def show(log = nil)
34
38
  say_error "No Cloudfile found" unless Cloudfile.present?
35
39
  specify_log(log)
36
- multiple_clouds(cloud, "deploys show #{log}", "Select log and cloud to view deploy logs using:")
40
+ multiple_clouds(options[:cloud], "deploys show #{log}", "Select log and cloud to view deploy logs using:")
37
41
  content = @app.deploy_log(log)
38
42
  say "Log for deploy done on #{content["created_at"]}", :green
39
43
  if content["bundle_install"]
@@ -161,11 +161,13 @@ module Shelly
161
161
  end
162
162
  end
163
163
 
164
- desc "start [CODE-NAME]", "Starts specific cloud"
165
- def start(cloud = nil)
164
+ desc "start", "Starts the cloud"
165
+ method_option :cloud, :type => :string, :aliases => "-c",
166
+ :desc => "Specify which cloud to start"
167
+ def start
166
168
  logged_in?
167
169
  say_error "No Cloudfile found" unless Cloudfile.present?
168
- multiple_clouds(cloud, "start", "Select which to start using:")
170
+ multiple_clouds(options[:cloud], "start", "Select cloud to start using:")
169
171
  @app.start
170
172
  say "Starting cloud #{@app.code_name}. Check status with:", :green
171
173
  say " shelly list"
@@ -195,11 +197,13 @@ module Shelly
195
197
  end
196
198
  end
197
199
 
198
- desc "stop [CODE-NAME]", "Stops specific cloud"
199
- def stop(cloud = nil)
200
+ desc "stop", "Stops the cloud"
201
+ method_option :cloud, :type => :string, :aliases => "-c",
202
+ :desc => "Specify which cloud to stop"
203
+ def stop
200
204
  logged_in?
201
205
  say_error "No Cloudfile found" unless Cloudfile.present?
202
- multiple_clouds(cloud, "stop", "Select which to stop using:")
206
+ multiple_clouds(options[:cloud], "stop", "Select cloud to stop using:")
203
207
  @app.stop
204
208
  say "Cloud '#{@app.code_name}' stopped"
205
209
  rescue Client::APIError => e
@@ -208,31 +212,28 @@ module Shelly
208
212
  end
209
213
  end
210
214
 
211
- desc "delete CODE-NAME", "Delete cloud from Shelly Cloud"
212
- def delete(code_name = nil)
215
+ desc "delete", "Delete cloud from Shelly Cloud"
216
+ method_option :cloud, :type => :string, :aliases => "-c",
217
+ :desc => "Specify which cloud to delete"
218
+ def delete
213
219
  user = Shelly::User.new
214
220
  user.token
215
- if code_name.present?
216
- app = Shelly::App.new(code_name)
217
- say "You are about to delete application: #{code_name}."
218
- say "Press Control-C at any moment to cancel."
219
- say "Please confirm each question by typing yes and pressing Enter."
220
- say_new_line
221
- ask_to_delete_files
222
- ask_to_delete_database
223
- ask_to_delete_application
224
- app.delete
225
- say_new_line
226
- say "Scheduling application delete - done"
227
- if App.inside_git_repository?
228
- app.remove_git_remote
229
- say "Removing git remote - done"
230
- else
231
- say "Missing git remote"
232
- end
221
+ multiple_clouds(options[:cloud], "delete", "Select cloud to delete using:")
222
+ say "You are about to delete application: #{@app.code_name}."
223
+ say "Press Control-C at any moment to cancel."
224
+ say "Please confirm each question by typing yes and pressing Enter."
225
+ say_new_line
226
+ ask_to_delete_files
227
+ ask_to_delete_database
228
+ ask_to_delete_application
229
+ @app.delete
230
+ say_new_line
231
+ say "Scheduling application delete - done"
232
+ if App.inside_git_repository?
233
+ @app.remove_git_remote
234
+ say "Removing git remote - done"
233
235
  else
234
- say_error "Missing CODE-NAME", :with_exit => false
235
- say_error "Use: shelly delete CODE-NAME"
236
+ say "Missing git remote"
236
237
  end
237
238
  rescue Client::APIError => e
238
239
  say_error e.message
@@ -245,13 +246,13 @@ module Shelly
245
246
  cloud = options[:cloud]
246
247
  logged_in?
247
248
  say_error "No Cloudfile found" unless Cloudfile.present?
248
- multiple_clouds(cloud, "logs --cloud", "Select which to show logs for using:")
249
+ multiple_clouds(cloud, "logs", "Select which to show logs for using:")
249
250
  begin
250
251
  logs = @app.application_logs
251
252
  say "Cloud #{@app.code_name}:", :green
252
253
  logs.each_with_index do |log, i|
253
- say "Instance #{i+1}:"
254
- print_wrapped log, :ident => 2
254
+ say "Instance #{i+1}:", :green
255
+ say log
255
256
  end
256
257
  rescue Client::APIError => e
257
258
  if e.unauthorized?
data/lib/shelly/client.rb CHANGED
@@ -62,6 +62,22 @@ module Shelly
62
62
  get("/apps/#{cloud}/configs")
63
63
  end
64
64
 
65
+ def app_config(cloud, id)
66
+ get("/apps/#{cloud}/configs/#{id}")
67
+ end
68
+
69
+ def app_create_config(cloud, path, content)
70
+ post("/apps/#{cloud}/configs", :config => {:path => path, :content => content})
71
+ end
72
+
73
+ def app_update_config(cloud, id, content)
74
+ put("/apps/#{cloud}/configs/#{id}", :config => {:content => content})
75
+ end
76
+
77
+ def app_delete_config(cloud, id)
78
+ delete("/apps/#{cloud}/configs/#{id}")
79
+ end
80
+
65
81
  def send_invitation(cloud, email)
66
82
  post("/apps/#{cloud}/collaborations", :email => email)
67
83
  end
@@ -61,7 +61,7 @@ module Shelly
61
61
  clouds = Cloudfile.new.clouds
62
62
  if clouds.count > 1 && cloud.nil?
63
63
  say "You have multiple clouds in Cloudfile. #{message}"
64
- say " shelly #{action} #{clouds.first}"
64
+ say " shelly #{action} --cloud #{clouds.first}"
65
65
  say "Available clouds:"
66
66
  clouds.each do |cloud|
67
67
  say " * #{cloud}"
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.0.32"
2
+ VERSION = "0.0.33"
3
3
  end
@@ -38,8 +38,8 @@ describe Shelly::CLI::Backup do
38
38
  end
39
39
 
40
40
  it "should show information to select specific cloud and exit" do
41
- $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select cloud to view database backups using:")
42
- $stdout.should_receive(:puts).with(" shelly backup list foo-production")
41
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select cloud to view database backups for using:")
42
+ $stdout.should_receive(:puts).with(" shelly backup list --cloud foo-production")
43
43
  $stdout.should_receive(:puts).with("Available clouds:")
44
44
  $stdout.should_receive(:puts).with(" * foo-production")
45
45
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -53,7 +53,8 @@ describe Shelly::CLI::Backup do
53
53
  $stdout.should_receive(:puts).with(" Filename | Size")
54
54
  $stdout.should_receive(:puts).with(" backup.postgre.tar.gz | 10kb")
55
55
  $stdout.should_receive(:puts).with(" backup.mongo.tar.gz | 22kb")
56
- @backup.list("foo-staging")
56
+ @backup.options = {:cloud => 'foo-staging'}
57
+ @backup.list
57
58
  end
58
59
  end
59
60
  end
@@ -10,14 +10,18 @@ describe Shelly::CLI::Config do
10
10
  Shelly::Client.stub(:new).and_return(@client)
11
11
  $stdout.stub(:puts)
12
12
  $stdout.stub(:print)
13
+ FileUtils.mkdir_p("/projects/foo")
14
+ Dir.chdir("/projects/foo")
15
+ @client.stub(:token).and_return("abc")
16
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\n") }
17
+ FileUtils.mkdir_p("/tmp")
18
+ Dir.stub(:tmpdir).and_return("/tmp")
19
+ ENV["EDITOR"] = "vim"
13
20
  end
14
21
 
15
22
  describe "#list" do
16
23
  before do
17
- FileUtils.mkdir_p("/projects/foo")
18
- Dir.chdir("/projects/foo")
19
24
  File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
20
- @client.stub(:token).and_return("abc")
21
25
  end
22
26
 
23
27
  it "should exit with message if there is no Cloudfile" do
@@ -37,19 +41,201 @@ describe Shelly::CLI::Config do
37
41
  end
38
42
 
39
43
  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"}])
44
+ @client.should_receive(:app_configs).with("foo-staging").and_return([{"id" => 1, "created_by_user" => true, "path" => "config/settings.yml"}])
45
+ @client.should_receive(:app_configs).with("foo-production").and_return([{"id" => 2, "created_by_user" => false, "path" => "config/app.yml"}])
42
46
  $stdout.should_receive(:puts).with(green "Configuration files for foo-production")
43
47
  $stdout.should_receive(:puts).with("You have no custom configuration files.")
44
48
  $stdout.should_receive(:puts).with("Following files are created by Shelly Cloud:")
45
- $stdout.should_receive(:puts).with(" * config/app.yml")
49
+ $stdout.should_receive(:puts).with(/ * 2\s+config\/app.yml/)
46
50
  $stdout.should_receive(:puts).with(green "Configuration files for foo-staging")
47
51
  $stdout.should_receive(:puts).with("Custom configuration files:")
48
- $stdout.should_receive(:puts).with(" * config/settings.yml")
52
+ $stdout.should_receive(:puts).with(/ * 1\s+config\/settings.yml/)
49
53
 
50
54
  @config.list
51
55
  end
52
56
 
53
57
  end
54
58
 
59
+ describe "#show" do
60
+ it "should exit with message if there is no Cloudfile" do
61
+ File.delete("Cloudfile")
62
+ $stdout.should_receive(:puts).with(red "No Cloudfile found")
63
+ lambda { @config.show(1) }.should raise_error(SystemExit)
64
+ end
65
+
66
+ it "should exit if no id was specified" do
67
+ $stdout.should_receive(:puts).with(red "No configuration file specified")
68
+ lambda { @config.show }.should raise_error(SystemExit)
69
+ end
70
+
71
+ it "should show config" do
72
+ @client.should_receive(:app_config).with("foo-staging", 1).and_return({"path" => "test.rb", "content" => "example content"})
73
+ $stdout.should_receive(:puts).with(green "Content of test.rb:")
74
+ $stdout.should_receive(:puts).with("example content")
75
+ @config.show(1)
76
+ end
77
+
78
+ context "multiple clouds" do
79
+ before do
80
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
81
+ end
82
+
83
+ it "should show info to select cloud and exit" do
84
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Specify cloud using:")
85
+ lambda { @config.show(1) }.should raise_error(SystemExit)
86
+ end
87
+
88
+ it "should use cloud specified by parameter" do
89
+ @client.should_receive(:app_config).with("foo-production", 1).and_return({"path" => "test.rb", "content" => "example content"})
90
+ @config.options = {:cloud => "foo-production"}
91
+ @config.show(1)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#create" do
97
+ it "should exit with message if there is no Cloudfile" do
98
+ File.delete("Cloudfile")
99
+ $stdout.should_receive(:puts).with(red "No Cloudfile found")
100
+ lambda { @config.create("path") }.should raise_error(SystemExit)
101
+ end
102
+
103
+ it "should exit if no id was specified" do
104
+ $stdout.should_receive(:puts).with(red "No path specified")
105
+ lambda { @config.create }.should raise_error(SystemExit)
106
+ end
107
+
108
+ it "should ask to set EDITOR environment variable if not set" do
109
+ @config.stub(:system) {false}
110
+ $stdout.should_receive(:puts).with(red "Please set EDITOR environment variable")
111
+ lambda { @config.create("path") }.should raise_error(SystemExit)
112
+ end
113
+
114
+ it "should create file" do
115
+ @config.should_receive(:system).with(/vim \/tmp\/shelly-edit/).and_return(true)
116
+ @client.should_receive(:app_create_config).with("foo-staging", "path", "\n").and_return({})
117
+ $stdout.should_receive(:puts).with(green "File 'path' created, it will be used after next code deploy")
118
+ @config.create("path")
119
+ end
120
+
121
+ context "multiple clouds" do
122
+ before do
123
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
124
+ end
125
+
126
+ it "should show info to select cloud and exit" do
127
+ @config.stub(:system) {true}
128
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Specify cloud using:")
129
+ lambda { @config.create("path") }.should raise_error(SystemExit)
130
+ end
131
+
132
+ it "should use cloud specified by parameter" do
133
+ @config.should_receive(:system).with(/vim \/tmp\/shelly-edit/).and_return(true)
134
+ @client.should_receive(:app_create_config).with("foo-production", "path", "\n").and_return({})
135
+ @config.options = {:cloud => "foo-production"}
136
+ @config.create("path")
137
+ end
138
+ end
139
+ end
140
+
141
+
142
+ describe "#edit" do
143
+ it "should exit with message if there is no Cloudfile" do
144
+ File.delete("Cloudfile")
145
+ $stdout.should_receive(:puts).with(red "No Cloudfile found")
146
+ lambda { @config.edit(1) }.should raise_error(SystemExit)
147
+ end
148
+
149
+ it "should exit if no path was specified" do
150
+ $stdout.should_receive(:puts).with(red "No configuration file specified")
151
+ lambda { @config.edit }.should raise_error(SystemExit)
152
+ end
153
+
154
+ it "should ask to set EDITOR environment variable if not set" do
155
+ @client.should_receive(:app_config).with("foo-staging", 1).and_return({"path" => "test.rb", "content" => "example content"})
156
+ @config.stub(:system) {false}
157
+ $stdout.should_receive(:puts).with(red "Please set EDITOR environment variable")
158
+ lambda { @config.edit(1) }.should raise_error(SystemExit)
159
+ end
160
+
161
+ it "should create file" do
162
+ @client.should_receive(:app_config).with("foo-staging", 1).and_return({"path" => "test.rb", "content" => "example content"})
163
+ @config.should_receive(:system).with(/vim \/tmp\/shelly-edit/).and_return(true)
164
+ @client.should_receive(:app_update_config).with("foo-staging", 1, "example content\n").and_return({"path" => "test.rb", "content" => "example content"})
165
+ $stdout.should_receive(:puts).with(green "File 'test.rb' updated, it will be used after next code deploy")
166
+ @config.edit(1)
167
+ end
168
+
169
+ context "multiple clouds" do
170
+ before do
171
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
172
+ end
173
+
174
+ it "should show info to select cloud and exit" do
175
+ @config.stub(:system) {true}
176
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Specify cloud using:")
177
+ lambda { @config.edit(1) }.should raise_error(SystemExit)
178
+ end
179
+
180
+ it "should use cloud specified by parameter" do
181
+ @client.should_receive(:app_config).with("foo-production", 1).and_return({"path" => "test.rb", "content" => "example content"})
182
+ @config.should_receive(:system).with(/vim \/tmp\/shelly-edit/).and_return(true)
183
+ @client.should_receive(:app_update_config).with("foo-production", 1, "example content\n").and_return({"path" => "test.rb", "content" => "example content"})
184
+ @config.options = {:cloud => "foo-production"}
185
+ @config.edit(1)
186
+ end
187
+ end
188
+ end
189
+
190
+ describe "#delete" do
191
+ it "should exit with message if there is no Cloudfile" do
192
+ File.delete("Cloudfile")
193
+ $stdout.should_receive(:puts).with(red "No Cloudfile found")
194
+ lambda { @config.delete(1) }.should raise_error(SystemExit)
195
+ end
196
+
197
+ it "should exit if no path was specified" do
198
+ $stdout.should_receive(:puts).with(red "No configuration file specified")
199
+ lambda { @config.delete }.should raise_error(SystemExit)
200
+ end
201
+
202
+ it "should delete configuration file" do
203
+ @client.should_receive(:app_config).with("foo-staging", 1).and_return({"path" => "test.rb", "content" => "example content"})
204
+ @client.should_receive(:app_delete_config).with("foo-staging", 1).and_return({})
205
+ $stdout.should_receive(:puts).with(green "File deleted, redeploy your cloud to make changes")
206
+ fake_stdin(["y"]) do
207
+ @config.delete(1)
208
+ end
209
+ end
210
+
211
+ it "should not delete file if user answered other than yes/y" do
212
+ @client.should_receive(:app_config).with("foo-staging", 1).and_return({"path" => "test.rb", "content" => "example content"})
213
+ @client.should_not_receive(:app_delete_config)
214
+ $stdout.should_receive(:puts).with("File not deleted")
215
+ fake_stdin(["n"]) do
216
+ @config.delete(1)
217
+ end
218
+ end
219
+
220
+ context "multiple clouds" do
221
+ before do
222
+ File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\nfoo-production:\n") }
223
+ end
224
+
225
+ it "should show info to select cloud and exit" do
226
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Specify cloud using:")
227
+ lambda { @config.delete(1) }.should raise_error(SystemExit)
228
+ end
229
+
230
+ it "should use cloud specified by parameter" do
231
+ @client.should_receive(:app_config).with("foo-production", 1).and_return({"path" => "test.rb", "content" => "example content"})
232
+ @client.should_receive(:app_delete_config).with("foo-production", 1).and_return({})
233
+ $stdout.should_receive(:puts).with(green "File deleted, redeploy your cloud to make changes")
234
+ @config.options = {:cloud => "foo-production"}
235
+ fake_stdin(["y"]) do
236
+ @config.delete(1)
237
+ end
238
+ end
239
+ end
240
+ end
55
241
  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 deploys list foo-production")
45
+ $stdout.should_receive(:puts).with(" shelly deploys list --cloud 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")
@@ -53,7 +53,8 @@ describe Shelly::CLI::Deploys do
53
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
- @deploys.list("foo-staging")
56
+ @deploys.options = {:cloud => "foo-staging"}
57
+ @deploys.list
57
58
  end
58
59
  end
59
60
 
@@ -99,7 +100,7 @@ describe Shelly::CLI::Deploys do
99
100
 
100
101
  it "should show information to select specific cloud and exit" do
101
102
  $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(" shelly deploys show last --cloud foo-production")
103
104
  $stdout.should_receive(:puts).with("Available clouds:")
104
105
  $stdout.should_receive(:puts).with(" * foo-production")
105
106
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -109,7 +110,8 @@ describe Shelly::CLI::Deploys do
109
110
  it "should render the logs" do
110
111
  @client.should_receive(:deploy_log).with("foo-staging", "last").and_return(response)
111
112
  expected_output
112
- @deploys.show("last", "foo-staging")
113
+ @deploys.options = {:cloud => "foo-staging"}
114
+ @deploys.show("last")
113
115
  end
114
116
  end
115
117
 
@@ -26,7 +26,7 @@ Tasks:
26
26
  shelly add # Adds new cloud to Shelly Cloud
27
27
  shelly backup <command> # Manages database backups from this cloud
28
28
  shelly config <command> # Manages cloud configuration files
29
- shelly delete CODE-NAME # Delete cloud from Shelly Cloud
29
+ shelly delete # Delete cloud from Shelly Cloud
30
30
  shelly deploys <command> # View cloud deploy logs
31
31
  shelly help [TASK] # Describe available tasks or one specific task
32
32
  shelly ip # Lists clouds IP's
@@ -34,8 +34,8 @@ Tasks:
34
34
  shelly login [EMAIL] # Logs user in to Shelly Cloud
35
35
  shelly logs # Show latest application logs from each instance
36
36
  shelly register [EMAIL] # Registers new user account on Shelly Cloud
37
- shelly start [CODE-NAME] # Starts specific cloud
38
- shelly stop [CODE-NAME] # Stops specific cloud
37
+ shelly start # Starts the cloud
38
+ shelly stop # Stops the cloud
39
39
  shelly user <command> # Manages users using this cloud
40
40
  shelly version # Displays shelly version
41
41
 
@@ -538,8 +538,8 @@ OUT
538
538
  end
539
539
 
540
540
  it "should show information to start specific cloud and exit" do
541
- $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select which to start using:")
542
- $stdout.should_receive(:puts).with(" shelly start foo-production")
541
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select cloud to start using:")
542
+ $stdout.should_receive(:puts).with(" shelly start --cloud foo-production")
543
543
  $stdout.should_receive(:puts).with("Available clouds:")
544
544
  $stdout.should_receive(:puts).with(" * foo-production")
545
545
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -550,7 +550,8 @@ OUT
550
550
  @client.should_receive(:start_cloud).with("foo-staging")
551
551
  $stdout.should_receive(:puts).with(green "Starting cloud foo-staging. Check status with:")
552
552
  $stdout.should_receive(:puts).with(" shelly list")
553
- @main.start("foo-staging")
553
+ @main.options = {:cloud => "foo-staging"}
554
+ @main.start
554
555
  end
555
556
  end
556
557
 
@@ -654,8 +655,8 @@ OUT
654
655
  end
655
656
 
656
657
  it "should show information to start specific cloud and exit" do
657
- $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select which to stop using:")
658
- $stdout.should_receive(:puts).with(" shelly stop foo-production")
658
+ $stdout.should_receive(:puts).with("You have multiple clouds in Cloudfile. Select cloud to stop using:")
659
+ $stdout.should_receive(:puts).with(" shelly stop --cloud foo-production")
659
660
  $stdout.should_receive(:puts).with("Available clouds:")
660
661
  $stdout.should_receive(:puts).with(" * foo-production")
661
662
  $stdout.should_receive(:puts).with(" * foo-staging")
@@ -665,7 +666,8 @@ OUT
665
666
  it "should fetch from command line which cloud to start" do
666
667
  @client.should_receive(:stop_cloud).with("foo-staging")
667
668
  $stdout.should_receive(:puts).with("Cloud 'foo-staging' stopped")
668
- @main.stop("foo-staging")
669
+ @main.options = {:cloud => "foo-staging"}
670
+ @main.stop
669
671
  end
670
672
  end
671
673
  end
@@ -734,9 +736,14 @@ OUT
734
736
  Shelly::App.stub(:new).and_return(@app)
735
737
  end
736
738
 
737
- context "when code_name is not nil" do
739
+ context "when cloud is given" do
740
+ before do
741
+ File.open("Cloudfile", 'w') {|f|
742
+ f.write("foo-staging:\nfoo-production:\n") }
743
+ end
744
+
738
745
  it "should ask about delete application parts" do
739
- $stdout.should_receive(:puts).with("You are about to delete application: foo-bar.")
746
+ $stdout.should_receive(:puts).with("You are about to delete application: foo-staging.")
740
747
  $stdout.should_receive(:puts).with("Press Control-C at any moment to cancel.")
741
748
  $stdout.should_receive(:puts).with("Please confirm each question by typing yes and pressing Enter.")
742
749
  $stdout.should_receive(:puts).with("\n")
@@ -747,7 +754,8 @@ OUT
747
754
  $stdout.should_receive(:puts).with("Scheduling application delete - done")
748
755
  $stdout.should_receive(:puts).with("Removing git remote - done")
749
756
  fake_stdin(["yes", "yes", "yes"]) do
750
- @main.delete("foo-bar")
757
+ @main.options = {:cloud => "foo-staging"}
758
+ @main.delete
751
759
  end
752
760
  end
753
761
 
@@ -755,23 +763,35 @@ OUT
755
763
  @app.should_not_receive(:delete)
756
764
  lambda{
757
765
  fake_stdin(["yes", "yes", "no"]) do
758
- @main.delete("foo-bar")
766
+ @main.options = {:cloud => "foo-staging"}
767
+ @main.delete
759
768
  end
760
769
  }.should raise_error(SystemExit)
761
770
  end
762
771
  end
763
772
 
764
773
  context "when git repository doesn't exist" do
774
+ before do
775
+ File.open("Cloudfile", 'w') {|f|
776
+ f.write("foo-staging:\n") }
777
+ end
778
+
765
779
  it "should say that Git remote missing" do
766
780
  Shelly::App.stub(:inside_git_repository?).and_return(false)
767
781
  $stdout.should_receive(:puts).with("Missing git remote")
768
782
  fake_stdin(["yes", "yes", "yes"]) do
769
- @main.delete("foo-bar")
783
+ @main.options = {:cloud => "foo-staging"}
784
+ @main.delete
770
785
  end
771
786
  end
772
787
  end
773
788
 
774
- context "when application with CODE-NAME doesn't exist" do
789
+ context "when cloud given in option doesn't exist" do
790
+ before do
791
+ File.open("Cloudfile", 'w') {|f|
792
+ f.write("foo-staging:\n") }
793
+ end
794
+
775
795
  it "should raise Client::APIError" do
776
796
  response = {:message => "Application not found"}
777
797
  exception = Shelly::Client::APIError.new(response.to_json)
@@ -779,17 +799,33 @@ OUT
779
799
  $stdout.should_receive(:puts).with("\e[31mApplication not found\e[0m")
780
800
  lambda{
781
801
  fake_stdin(["yes", "yes", "yes"]) do
782
- @main.delete("foo-bar")
802
+ @main.options = {:cloud => "foo-bar"}
803
+ @main.delete
783
804
  end
784
805
  }.should raise_error(SystemExit)
785
806
  end
786
807
  end
787
808
 
788
- context "when code_name is nil" do
789
- it "should display error when no code_name" do
790
- $stdout.should_receive(:puts).with("\e[31mMissing CODE-NAME\e[0m")
791
- $stdout.should_receive(:puts).with("\e[31mUse: shelly delete CODE-NAME\e[0m")
792
- lambda{ @main.delete }.should raise_error(SystemExit)
809
+ context "when no cloud option is given" do
810
+ before do
811
+ File.open("Cloudfile", 'w') {|f|
812
+ f.write("foo-staging:\n") }
813
+ end
814
+
815
+ it "should take the cloud from Cloudfile" do
816
+ $stdout.should_receive(:puts).with("You are about to delete application: foo-staging.")
817
+ $stdout.should_receive(:puts).with("Press Control-C at any moment to cancel.")
818
+ $stdout.should_receive(:puts).with("Please confirm each question by typing yes and pressing Enter.")
819
+ $stdout.should_receive(:puts).with("\n")
820
+ $stdout.should_receive(:print).with("I want to delete all files stored on Shelly Cloud (yes/no): ")
821
+ $stdout.should_receive(:print).with("I want to delete all database data stored on Shelly Cloud (yes/no): ")
822
+ $stdout.should_receive(:print).with("I want to delete the application (yes/no): ")
823
+ $stdout.should_receive(:puts).with("\n")
824
+ $stdout.should_receive(:puts).with("Scheduling application delete - done")
825
+ $stdout.should_receive(:puts).with("Removing git remote - done")
826
+ fake_stdin(["yes", "yes", "yes"]) do
827
+ @main.delete
828
+ end
793
829
  end
794
830
  end
795
831
  end
@@ -839,8 +875,8 @@ OUT
839
875
  it "should show logs for the cloud" do
840
876
  @client.stub(:application_logs).and_return(["log1"])
841
877
  $stdout.should_receive(:puts).with(green "Cloud foo-production:")
842
- $stdout.should_receive(:puts).with("Instance 1:")
843
- $stdout.should_receive(:puts).with(" log1")
878
+ $stdout.should_receive(:puts).with(green "Instance 1:")
879
+ $stdout.should_receive(:puts).with("log1")
844
880
  @main.logs
845
881
  end
846
882
  end
@@ -865,8 +901,8 @@ OUT
865
901
  @client.should_receive(:application_logs).with("foo-staging").
866
902
  and_return(["log1"])
867
903
  $stdout.should_receive(:puts).with(green "Cloud foo-staging:")
868
- $stdout.should_receive(:puts).with("Instance 1:")
869
- $stdout.should_receive(:puts).with(" log1")
904
+ $stdout.should_receive(:puts).with(green "Instance 1:")
905
+ $stdout.should_receive(:puts).with("log1")
870
906
  @main.options = {:cloud => "foo-staging"}
871
907
  @main.logs
872
908
  end
@@ -876,10 +912,10 @@ OUT
876
912
  it "should show logs from each instance" do
877
913
  @client.stub(:application_logs).and_return(["log1", "log2"])
878
914
  $stdout.should_receive(:puts).with(green "Cloud foo-production:")
879
- $stdout.should_receive(:puts).with("Instance 1:")
880
- $stdout.should_receive(:puts).with(" log1")
881
- $stdout.should_receive(:puts).with("Instance 2:")
882
- $stdout.should_receive(:puts).with(" log2")
915
+ $stdout.should_receive(:puts).with(green "Instance 1:")
916
+ $stdout.should_receive(:puts).with("log1")
917
+ $stdout.should_receive(:puts).with(green "Instance 2:")
918
+ $stdout.should_receive(:puts).with("log2")
883
919
  @main.logs
884
920
  end
885
921
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
3
  version: !ruby/object:Gem::Version
4
- hash: 95
4
+ hash: 93
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 32
10
- version: 0.0.32
9
+ - 33
10
+ version: 0.0.33
11
11
  platform: ruby
12
12
  authors:
13
13
  - Shelly Cloud team
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-12-19 00:00:00 Z
18
+ date: 2011-12-26 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec