shelly 0.1.18 → 0.1.19

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ class String
2
+ def dasherize
3
+ self.tr('_', '-')
4
+ end
5
+
6
+ def humanize
7
+ self.tr('_', ' ')
8
+ end
9
+ end
data/lib/shelly.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "rubygems"
2
2
  require "core_ext/object"
3
3
  require "core_ext/hash"
4
+ require "core_ext/string"
4
5
 
5
6
  require "yaml"
6
7
  if YAML.const_defined?(:ENGINE)
data/lib/shelly/app.rb CHANGED
@@ -92,8 +92,10 @@ module Shelly
92
92
  shelly.restore_backup(code_name, filename)
93
93
  end
94
94
 
95
- def request_backup(kind)
96
- shelly.request_backup(code_name, kind)
95
+ def request_backup(kinds)
96
+ Array(kinds).each do |kind|
97
+ shelly.request_backup(code_name, kind)
98
+ end
97
99
  end
98
100
 
99
101
  def logs
@@ -126,7 +128,7 @@ module Shelly
126
128
  end
127
129
  end
128
130
  end
129
- "#{File.basename(Dir.pwd)}-#{guessed || 'staging'}".downcase.tr('_','-')
131
+ "#{File.basename(Dir.pwd)}-#{guessed || 'staging'}".downcase.dasherize
130
132
  end
131
133
 
132
134
  def collaborations
data/lib/shelly/backup.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Shelly
2
2
  class Backup < Model
3
- attr_reader :filename, :size, :human_size, :code_name, :kind
3
+ attr_reader :filename, :size, :human_size, :code_name, :kind, :state
4
4
 
5
5
  def initialize(attributes = {})
6
6
  @filename = attributes["filename"]
@@ -8,6 +8,7 @@ module Shelly
8
8
  @human_size = attributes["human_size"]
9
9
  @code_name = attributes["code_name"]
10
10
  @kind = attributes["kind"]
11
+ @state = attributes["state"]
11
12
  end
12
13
 
13
14
  def download(callback)
@@ -17,9 +17,9 @@ module Shelly
17
17
  app = multiple_clouds(options[:cloud], "backup list")
18
18
  backups = app.database_backups
19
19
  if backups.present?
20
- to_display = [["Filename", "| Size"]]
20
+ to_display = [["Filename", "| Size", "| State"]]
21
21
  backups.each do |backup|
22
- to_display << [backup.filename, "| #{backup.human_size}"]
22
+ to_display << [backup.filename, "| #{backup.human_size}", "| #{backup.state.humanize}"]
23
23
  end
24
24
 
25
25
  say "Available backups:", :green
@@ -53,15 +53,22 @@ module Shelly
53
53
  desc "create [DB_KIND]", "Create backup of given database"
54
54
  long_desc %{
55
55
  Create backup of given database.
56
- If database kind is not specified, backup of all configured databases will be performed.
56
+ If database kind is not specified, Cloudfile must be present to backup all configured databases.
57
57
  }
58
58
  def create(kind = nil)
59
59
  app = multiple_clouds(options[:cloud], "backup create [DB_KIND]")
60
- app.request_backup(kind)
60
+ cloudfile = Cloudfile.new
61
+ unless kind || cloudfile.present?
62
+ say_error "Cloudfile must be present in current working directory or specify database kind with:", :with_exit => false
63
+ say_error "`shelly backup create DB_KIND`"
64
+ end
65
+ app.request_backup(kind || cloudfile.backup_databases(app))
61
66
  say "Backup requested. It can take up to several minutes for " +
62
- "the backup process to finish and the backup to show up in backups list.", :green
67
+ "the backup process to finish.", :green
63
68
  rescue Client::ValidationException => e
64
69
  say_error e[:message]
70
+ rescue Client::ConflictException => e
71
+ say_error e[:message]
65
72
  end
66
73
 
67
74
  desc "restore FILENAME", "Restore database to state from given backup"
@@ -78,6 +85,8 @@ module Shelly
78
85
  raise unless e.resource == :database_backup
79
86
  say_error "Backup not found", :with_exit => false
80
87
  say "You can list available backups with `shelly backup list` command"
88
+ rescue Client::ConflictException => e
89
+ say_error e[:message]
81
90
  end
82
91
  end
83
92
  end
@@ -117,7 +117,7 @@ module Shelly
117
117
  e.each_error { |error| say_error error, :with_exit => false }
118
118
  say_new_line
119
119
  say_error "Fix erros in the below command and type it again to create your cloud" , :with_exit => false
120
- say_error "shelly add --code-name=#{app.code_name.downcase.tr('_','-')} --databases=#{app.databases.join(',')} --size=#{app.size}"
120
+ say_error "shelly add --code-name=#{app.code_name.downcase.dasherize} --databases=#{app.databases.join(',')} --size=#{app.size}"
121
121
  end
122
122
 
123
123
  map "status" => :list
@@ -132,7 +132,7 @@ module Shelly
132
132
  msg = if state == "deploy_failed" || state == "configuration_failed"
133
133
  " (deployment log: `shelly deploys show last -c #{app["code_name"]}`)"
134
134
  end
135
- [app["code_name"], "| #{state.gsub("_", " ")}#{msg}"]
135
+ [app["code_name"], "| #{state.humanize}#{msg}"]
136
136
  end
137
137
  print_table(apps_table, :ident => 2)
138
138
  else
@@ -35,6 +35,20 @@ module Shelly
35
35
  File.open(path, "a+") { |f| f << generate }
36
36
  end
37
37
 
38
+ # Public: Return databases for given Cloud in Cloudfile
39
+ # Returns Array of databases
40
+ def databases(cloud)
41
+ content[cloud.to_s]["servers"].map do |server, settings|
42
+ settings["databases"]
43
+ end.flatten.uniq
44
+ end
45
+
46
+ # Public: Return databases to backup for given Cloud in Cloudfile
47
+ # Returns Array of databases, except redis db
48
+ def backup_databases(cloud)
49
+ databases(cloud) - ['redis']
50
+ end
51
+
38
52
  private
39
53
 
40
54
  # Internal: Load and parse Cloudfile
@@ -1,3 +1,3 @@
1
1
  module Shelly
2
- VERSION = "0.1.18"
2
+ VERSION = "0.1.19"
3
3
  end
@@ -14,6 +14,7 @@ describe Shelly::Backup do
14
14
  backup.filename.should == "backup.tar.gz"
15
15
  backup.human_size.should == "2KB"
16
16
  backup.size.should == 2048
17
+ backup.state.should == "completed"
17
18
  end
18
19
 
19
20
  describe "#download" do
@@ -29,6 +30,7 @@ describe Shelly::Backup do
29
30
  {"code_name" => "foo",
30
31
  "filename" => "backup.tar.gz",
31
32
  "human_size" => "2KB",
32
- "size" => 2048}
33
+ "size" => 2048,
34
+ "state" => "completed"}
33
35
  end
34
36
  end
@@ -31,18 +31,22 @@ describe Shelly::CLI::Backup do
31
31
 
32
32
  # multiple_clouds is tested in main_spec.rb in describe "#start" block
33
33
  it "should ensure multiple_clouds check" do
34
- @client.should_receive(:database_backups).with("foo-staging").and_return([{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb", "size" => 12345}])
34
+ @client.should_receive(:database_backups).with("foo-staging").and_return([{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb", "size" => 12345, "state" => "completed"}])
35
35
  @backup.should_receive(:multiple_clouds).and_return(@app)
36
36
  invoke(@backup, :list)
37
37
  end
38
38
 
39
39
  it "should take cloud from command line for which to show backups" do
40
- @client.should_receive(:database_backups).with("foo-staging").and_return([{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb", "size" => 12345},{"filename" => "backup.mongo.tar.gz", "human_size" => "22kb", "size" => 333}])
40
+ @client.should_receive(:database_backups).with("foo-staging").and_return(
41
+ [{"filename" => "backup.postgre.tar.gz", "human_size" => "10kb",
42
+ "size" => 12345, "state" => "completed"},
43
+ {"filename" => "backup.mongo.tar.gz", "human_size" => "22kb",
44
+ "size" => 333, "state" => "in_progress"}])
41
45
  $stdout.should_receive(:puts).with(green "Available backups:")
42
46
  $stdout.should_receive(:puts).with("\n")
43
- $stdout.should_receive(:puts).with(" Filename | Size")
44
- $stdout.should_receive(:puts).with(" backup.postgre.tar.gz | 10kb")
45
- $stdout.should_receive(:puts).with(" backup.mongo.tar.gz | 22kb")
47
+ $stdout.should_receive(:puts).with(" Filename | Size | State")
48
+ $stdout.should_receive(:puts).with(" backup.postgre.tar.gz | 10kb | completed")
49
+ $stdout.should_receive(:puts).with(" backup.mongo.tar.gz | 22kb | in progress")
46
50
  @backup.options = {:cloud => "foo-staging"}
47
51
  invoke(@backup, :list)
48
52
  end
@@ -114,8 +118,9 @@ describe Shelly::CLI::Backup do
114
118
  before do
115
119
  FileUtils.mkdir_p("/projects/foo")
116
120
  Dir.chdir("/projects/foo")
117
- File.open("Cloudfile", 'w') {|f| f.write("foo-staging:\n") }
118
121
  $stdout.stub(:puts)
122
+ @cloudfile = mock(:backup_databases => ['postgresql', 'mongodb'], :clouds => ['foo-staging'])
123
+ Shelly::Cloudfile.stub(:new).and_return(@cloudfile)
119
124
  end
120
125
 
121
126
  it "should ensure user has logged in" do
@@ -137,12 +142,31 @@ describe Shelly::CLI::Backup do
137
142
  lambda { invoke(@backup, :create) }.should raise_error(SystemExit)
138
143
  end
139
144
 
145
+ it "should backup db specified by cli" do
146
+ @app.should_receive(:request_backup).with('postgresql')
147
+ invoke(@backup, :create, "postgresql")
148
+ end
149
+
150
+ it "should backup all dbs in cloudfile" do
151
+ @app.should_receive(:request_backup).with(['postgresql', 'mongodb'])
152
+ invoke(@backup, :create)
153
+ end
154
+
140
155
  it "should display information about request backup" do
141
156
  @client.stub(:request_backup)
142
157
  $stdout.should_receive(:puts).with(green "Backup requested. It can take up to several minutes for " +
143
- "the backup process to finish and the backup to show up in backups list.")
158
+ "the backup process to finish.")
144
159
  invoke(@backup, :create)
145
160
  end
161
+
162
+ it "should display information about missing kind or Cloudfile" do
163
+ @cloudfile.stub(:present?).and_return(false)
164
+ $stdout.should_receive(:puts).with(red "Cloudfile must be present in current working directory or specify database kind with:")
165
+ $stdout.should_receive(:puts).with(red "`shelly backup create DB_KIND`")
166
+
167
+ @backup.options = {:cloud => "foo-production"}
168
+ lambda { invoke(@backup, :create) }.should raise_error(SystemExit)
169
+ end
146
170
  end
147
171
 
148
172
  describe "restore" do
@@ -88,6 +88,31 @@ config
88
88
  end
89
89
  end
90
90
 
91
+ describe "#databases" do
92
+ before do
93
+ content = <<-config
94
+ foo-staging:
95
+ servers:
96
+ app1:
97
+ databases:
98
+ - postgresql
99
+ - redis
100
+ app2:
101
+ databases:
102
+ - mongodb
103
+ config
104
+ File.open("Cloudfile", 'w') {|f| f.write(content) }
105
+ end
106
+
107
+ it "should return databases in cloudfile" do
108
+ @cloudfile.databases("foo-staging").should =~ ['redis', 'mongodb', 'postgresql']
109
+ end
110
+
111
+ it "should return databases except for redis" do
112
+ @cloudfile.backup_databases("foo-staging").should =~ ['postgresql', 'mongodb']
113
+ end
114
+ end
115
+
91
116
  describe "#create" do
92
117
  before do
93
118
  @cloudfile.stub(:generate).and_return("foo-staging:")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shelly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.18
4
+ version: 0.1.19
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-23 00:00:00.000000000 Z
12
+ date: 2012-07-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -284,6 +284,7 @@ files:
284
284
  - bin/shelly
285
285
  - lib/core_ext/hash.rb
286
286
  - lib/core_ext/object.rb
287
+ - lib/core_ext/string.rb
287
288
  - lib/shelly.rb
288
289
  - lib/shelly/app.rb
289
290
  - lib/shelly/backup.rb