appscake 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -6,8 +6,8 @@ AppsCake - Web Frontend for AppScale Tools
6
6
  AppsCake is a simple and lightweight web application that allows users to
7
7
  interact with AppScale tools over the web. This way even those users who
8
8
  are not familiar with general cloud principles or those who are not
9
- comfortable with working with a traditional command line interface can
10
- get started with deploying AppScale clouds and AppScale cloud applications.
9
+ comfortable working with a traditional command line interface can get
10
+ started with deploying AppScale clouds and AppScale cloud applications.
11
11
 
12
12
  AppsCake has been developed using the Ruby programming language and is
13
13
  based on Sinatra. So far it has been tested in Xen and EC2 cloud
@@ -21,27 +21,33 @@ Following software is required to install and run AppsCake:
21
21
  1. Ruby interpreter
22
22
  2. Sinatra gem
23
23
  3. AppScale tools gem (or alternatively you can install AppScale tools
24
- binary distribution on your machine/VM and put them in the PATH)
24
+ binary distribution on your machine/VM and put it in the PATH)
25
25
 
26
26
  Installation
27
27
  ============
28
28
 
29
29
  There are 2 ways to install AppsCake:
30
30
 
31
- 1. Pull the source from the Github
32
- - https://github.com/AppScale/appscake
31
+ 1. Pull the latest source from the Github
32
+ git clone https://github.com/AppScale/appscake
33
33
 
34
34
  2. Install the AppsCake gem
35
35
  sudo gem install appscake
36
36
 
37
+ Gem installation will take care of installing the necessary dependencies
38
+ too.
39
+
37
40
  Running AppsCake
38
41
  ================
39
42
 
40
- To launch AppsCake, simply go into the bin directory and execute the
41
- 'appscake' script:
43
+ If you installed AppsCake from source, simply go into the 'bin' directory
44
+ of the installation and run the 'appscake' script.
42
45
 
43
46
  ./appscake
44
47
 
48
+ If you installed the AppsCake gem, simply execute the 'appscake' command
49
+ (which should be in your PATH).
50
+
45
51
  Once the server has started up, fire up your web browser and navigate
46
52
  to https://<appscake-host>:8443
47
53
 
@@ -52,5 +58,5 @@ security group so that it allows inbound traffic on the port 8443.
52
58
 
53
59
  ======================================================================
54
60
  AppsCake is a project by the UCSB RACELab
55
- http://appscake.cs.ucsb.edu
61
+ http://appscale.cs.ucsb.edu
56
62
 
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'rake/testtask'
7
7
  # TODO(cgb): This probably should be moved into a Gemfile and out of this file.
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'appscake'
10
- s.version = '0.0.2'
10
+ s.version = '0.0.3'
11
11
 
12
12
  s.summary = "A web interface to the AppScale command-line tools."
13
13
  s.description = <<-EOF
@@ -31,8 +31,13 @@ spec = Gem::Specification.new do |s|
31
31
  s.require_path = "lib"
32
32
  s.autorequire = "appscake_utils"
33
33
 
34
- s.has_rdoc = false
34
+ s.has_rdoc = false # to be fixed by 0.0.4
35
+
36
+ # Dependencies: AppsCake uses the AppScale Tools to run AppScale, net-ssh to
37
+ # copy over files, and the Sinatra web server to present a web UI to users.
38
+ s.add_dependency('appscale-tools', '>= 1.6.0')
35
39
  s.add_dependency('net-ssh', '>= 2.6.0')
40
+ s.add_dependency('sinatra', '>= 1.3.2')
36
41
  end
37
42
 
38
43
 
@@ -40,3 +45,16 @@ end
40
45
  Rake::GemPackageTask.new(spec) do |pkg|
41
46
  pkg.need_tar = true
42
47
  end
48
+
49
+ # responds to 'rake test'
50
+ Rake::TestTask.new do |test|
51
+ test.libs << "test"
52
+ test.test_files = Dir[ "test/test*.rb" ]
53
+ test.verbose = true
54
+ end
55
+
56
+ task :default => 'test'
57
+
58
+ task :coverage do
59
+ puts `bash generate_coverage.sh`
60
+ end
@@ -59,7 +59,8 @@ class AppsCake < Sinatra::Base
59
59
  if !params[:target_app].nil? and params[:target_app] != '_none_'
60
60
  puts params[:target_app]
61
61
  app_name = params[:target_app]
62
- file_location = File.join(File.dirname(__FILE__), "repository", params[:target_app])
62
+ file_location = File.join(File.dirname(__FILE__), "..",
63
+ "repository", params[:target_app])
63
64
  end
64
65
 
65
66
  run_instances_options = {
@@ -77,7 +78,15 @@ class AppsCake < Sinatra::Base
77
78
  'admin_pass' => params[:virtual_pass]
78
79
  }
79
80
 
80
- deploy_on_virtual_cluster(params, add_key_options, run_instances_options, yaml_result)
81
+ result = deploy_on_virtual_cluster(params, add_key_options, run_instances_options)
82
+ if result[0]
83
+ @timestamp = result[1]
84
+ @pid = result[2]
85
+ @html = yaml_result
86
+ return erb :success
87
+ else
88
+ report_error(result[1], result[2])
89
+ end
81
90
  end
82
91
 
83
92
  post '/iaas_ec2.do' do
@@ -109,7 +118,7 @@ class AppsCake < Sinatra::Base
109
118
  file_location = nil
110
119
  if !params[:target_app].nil? and params[:target_app] != '_none_'
111
120
  app_name = params[:target_app]
112
- file_location = File.join(File.dirname(__FILE__), "repository", params[:target_app])
121
+ file_location = File.join(File.dirname(__FILE__), "..", "repository", params[:target_app])
113
122
  end
114
123
 
115
124
  run_instances_options = {
@@ -130,7 +139,15 @@ class AppsCake < Sinatra::Base
130
139
  'admin_user' => params[:ec2_user],
131
140
  'admin_pass' => params[:ec2_pass],
132
141
  }
133
- deploy_on_ec2(params, run_instances_options, cert_timestamp)
142
+ result = deploy_on_ec2(params, run_instances_options, cert_timestamp)
143
+ if result[0]
144
+ @timestamp = result[1]
145
+ @pid = result[2]
146
+ @html = ""
147
+ return erb :success
148
+ else
149
+ report_error(result[1], result[2])
150
+ end
134
151
  end
135
152
 
136
153
  get '/view_logs' do
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ rm -rf coverage
3
+ rcov test/tc_appscake_utils.rb -x test/tc_appscake_utils.rb -x /var/lib/gems/ -x /usr/local/lib/site_ruby/1.8/rubygems/gem_path_searcher.rb -x ~/.rvm -x /usr/local/appscale-tools
@@ -3,14 +3,19 @@ require 'net/ssh'
3
3
  require 'yaml'
4
4
 
5
5
  tools_home = `which appscale-run-instances`
6
- if tools_home.length == 0
7
- # If AppScale-Tools are not installed on the local machine, use the Gem
8
- require 'appscale-tools'
9
- else
10
- # Give priority to the the local copy of AppScale Tools
11
- $:.unshift File.join(File.dirname(tools_home), "..", "lib")
12
- require 'appscale_tools'
6
+ if tools_home.length > 0
7
+ # AppScale-Tools are installed on the local machine
8
+ lib_dir = File.join(File.dirname(tools_home), "..", "lib")
9
+ tools_impl = File.join(lib_dir, "appscale_tools.rb")
10
+ if File.exists?(tools_impl)
11
+ # AppScale-Tools have been installed manually
12
+ # by building the source or by similar means.
13
+ # (as opposed to installing the appscale-tools gem)
14
+ # Add the lib directory into the load path.
15
+ $:.unshift lib_dir
16
+ end
13
17
  end
18
+ require 'appscale_tools'
14
19
 
15
20
  $mutex = Mutex.new
16
21
 
@@ -80,42 +85,33 @@ def validate_yaml(yaml_str)
80
85
  end
81
86
 
82
87
  yaml = YAML.load(yaml_str)
83
- critical_roles = %w[ appengine loadbalancer database login shadow zookeeper ]
84
- aggregate_roles = {
85
- 'master' => %w[ shadow loadbalancer zookeeper login ],
86
- 'controller' => %w[ shadow loadbalancer zookeeper database login ],
87
- 'servers' => %w[ appengine database loadbalancer ]
88
- }
89
- optional_roles = %w[ open memcache ]
90
-
91
- success_result = ''
92
- yaml.each do |symbol, value|
93
- role = symbol.to_s
94
- if !critical_roles.include? role and !aggregate_roles.has_key? role and
95
- !optional_roles.include? role
96
- return [false, "Unknown AppScale server role: #{role}"]
97
- else
98
- critical_roles.delete_if { |r|
99
- r == role or (aggregate_roles.has_key? role and aggregate_roles[role].include? r)
100
- }
101
- success_result += "<p>#{role}</p><ul>"
102
- if value.kind_of?(Array)
103
- value.each do |val|
104
- success_result += "<li>#{val}</li>"
88
+ node_layout = NodeLayout.new(yaml, {})
89
+ if !node_layout.valid?
90
+ errors = node_layout.errors
91
+ error_result = ""
92
+ for error in errors
93
+ if !error.nil? and error.length > 0
94
+ if error_result.length > 0
95
+ error_result += ", "
105
96
  end
106
- else
107
- success_result += "<li>#{value}</li>"
97
+ error_result += error
108
98
  end
109
- success_result += '</ul>'
110
99
  end
100
+ return [false, error_result]
111
101
  end
112
102
 
113
- if critical_roles.length > 0
114
- result = "Following required roles are not configured: "
115
- critical_roles.each do |role|
116
- result += "#{role}, "
103
+ success_result = ""
104
+ yaml.each do |symbol, value|
105
+ role = symbol.to_s
106
+ success_result += "<p>#{role}</p><ul>"
107
+ if value.kind_of?(Array)
108
+ value.each do |val|
109
+ success_result += "<li>#{val}</li>"
110
+ end
111
+ else
112
+ success_result += "<li>#{value}</li>"
117
113
  end
118
- return [false, result[0..-3]]
114
+ success_result += "</ul>"
119
115
  end
120
116
 
121
117
  [true, success_result, yaml]
@@ -160,7 +156,9 @@ def validate_ec2_credentials(username, access_key, secret_key, region)
160
156
  end
161
157
 
162
158
  def validate_ec2_certificate_uploads(username, pk_upload, cert_upload)
163
- if pk_upload.nil?
159
+ if username.nil? or username.length == 0
160
+ return [false, "EC2 username not specified"]
161
+ elsif pk_upload.nil?
164
162
  return [false, "Primary key not uploaded"]
165
163
  elsif pk_upload[:type] != "application/x-x509-ca-cert" and
166
164
  pk_upload[:type] != "application/x-pem-file"
@@ -172,10 +170,11 @@ def validate_ec2_certificate_uploads(username, pk_upload, cert_upload)
172
170
  return [false, "Invalid certificate format: #{cert_upload[:type]}"]
173
171
  else
174
172
  timestamp = Time.now.to_i
175
- File.open("certificates/#{username}_#{timestamp}_pk.pem", "w") do |f|
173
+ cert_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "certificates"))
174
+ File.open(File.join(cert_dir, "#{username}_#{timestamp}_pk.pem"), "w") do |f|
176
175
  f.write(pk_upload[:tempfile].read)
177
176
  end
178
- File.open("certificates/#{username}_#{timestamp}_cert.pem", "w") do |f|
177
+ File.open(File.join(cert_dir, "#{username}_#{timestamp}_cert.pem"), "w") do |f|
179
178
  f.write(cert_upload[:tempfile].read)
180
179
  end
181
180
  end
@@ -227,7 +226,7 @@ def redirect_standard_io(timestamp)
227
226
  begin
228
227
  orig_stderr = $stderr.clone
229
228
  orig_stdout = $stdout.clone
230
- log_path = File.join(File.expand_path(File.dirname(__FILE__)), "logs")
229
+ log_path = File.join(File.expand_path(File.dirname(__FILE__)), "..", "logs")
231
230
  $stderr.reopen File.new(File.join(log_path, "deploy-#{timestamp}.log"), "w")
232
231
  $stderr.sync = true
233
232
  $stdout.reopen File.new(File.join(log_path, "deploy-#{timestamp}.log"), "w")
@@ -245,18 +244,25 @@ def redirect_standard_io(timestamp)
245
244
  retval
246
245
  end
247
246
 
248
- def deploy_on_virtual_cluster(params, add_key_options, run_instances_options, success_msg)
247
+ # Initiates a task in the background to deploy AppScale on a virtualized
248
+ # cluster. Returns a 3-element array as the result of the operation. The
249
+ # first element of the array is a boolean value indicating success or
250
+ # failure. In case of success, the second value will be the timestamp
251
+ # on which the task was launched. The third value will be the process ID
252
+ # of the newly launched task. In case of failure the second and third values
253
+ # will provide detailed error information.
254
+ def deploy_on_virtual_cluster(params, add_key_options, run_instances_options)
249
255
  if lock
250
256
  begin
251
257
  timestamp = Time.now.to_i
252
258
  pid = fork do
253
259
  begin
254
260
  redirect_standard_io(timestamp) do
255
- key_file = File.expand_path("~/.appscale/#{params[:keyname]}")
261
+ key_file = File.expand_path("~/.appscale/#{params[:virtual_keyname]}")
256
262
  if File.exists?(key_file)
257
- puts "AppScale key '#{params[:keyname]}' found on the disk. Reusing..."
263
+ puts "AppScale key '#{params[:virtual_keyname]}' found on the disk. Reusing..."
258
264
  else
259
- puts "AppScale key '#{params[:keyname]}' not found on the disk. Generating..."
265
+ puts "AppScale key '#{params[:virtual_keyname]}' not found on the disk. Generating..."
260
266
  AppScaleTools.add_keypair(add_key_options)
261
267
  end
262
268
  AppScaleTools.run_instances(run_instances_options)
@@ -267,19 +273,16 @@ def deploy_on_virtual_cluster(params, add_key_options, run_instances_options, su
267
273
  end
268
274
  end
269
275
  Process.detach(pid)
270
- @timestamp = timestamp
271
- @pid = pid
272
- @html = success_msg
273
- return erb :success
276
+ return [true, timestamp, pid]
274
277
  rescue Exception => e
275
278
  # If something went wrong with the fork, release the lock immediately and return
276
279
  unlock
277
- return report_error("Unexpected Runtime Error", "Runtime error while executing" +
278
- " appscale tools: #{e.message}")
280
+ return [false, "Unexpected Runtime Error", "Runtime error while executing" +
281
+ " appscale tools: #{e.message}"]
279
282
  end
280
283
  else
281
- return report_error("Server Busy", "AppsCake is currently busy deploying a cloud." +
282
- " Please try again later.")
284
+ return [false, "Server Busy", "AppsCake is currently busy deploying a cloud." +
285
+ " Please try again later."]
283
286
  end
284
287
  end
285
288
 
@@ -289,9 +292,9 @@ def deploy_on_ec2(params, run_instances_options, cert_timestamp)
289
292
  timestamp = Time.now.to_i
290
293
  pid = fork do
291
294
  ENV['EC2_REGION'] = params[:region]
292
- ENV['EC2_PRIVATE_KEY'] = File.join(File.dirname(__FILE__), "certificates",
295
+ ENV['EC2_PRIVATE_KEY'] = File.join(File.dirname(__FILE__), "..", "certificates",
293
296
  "#{params[:username]}_#{cert_timestamp}_pk.pem")
294
- ENV['EC2_CERT'] = File.join(File.dirname(__FILE__), "certificates",
297
+ ENV['EC2_CERT'] = File.join(File.dirname(__FILE__), "..", "certificates",
295
298
  "#{params[:username]}_#{cert_timestamp}_cert.pem")
296
299
  ENV['EC2_ACCESS_KEY'] = params[:access_key]
297
300
  ENV['EC2_SECRET_KEY'] = params[:secret_key]
@@ -308,18 +311,15 @@ def deploy_on_ec2(params, run_instances_options, cert_timestamp)
308
311
  end
309
312
  end
310
313
  Process.detach(pid)
311
- @timestamp = timestamp
312
- @pid = pid
313
- @html = ""
314
- return erb :success
314
+ return [true, timestamp, pid]
315
315
  rescue Exception => e
316
316
  # If something went wrong with the fork, release the lock immediately and return
317
317
  unlock
318
- return report_error("Unexpected Runtime Error", "Runtime error while executing" +
319
- " appscale tools: #{e.message}")
318
+ return [false, "Unexpected Runtime Error", "Runtime error while executing" +
319
+ " appscale tools: #{e.message}"]
320
320
  end
321
321
  else
322
- return report_error("Server Busy", "AppsCake is currently busy deploying a cloud." +
323
- " Please try again later.")
322
+ return [false, "Server Busy", "AppsCake is currently busy deploying a cloud." +
323
+ " Please try again later."]
324
324
  end
325
325
  end
@@ -0,0 +1,250 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'flexmock/test_unit'
4
+
5
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
6
+ require 'appscake_utils'
7
+
8
+ class TestInputValidation < Test::Unit::TestCase
9
+
10
+ def test_validate_appscale_credentials
11
+ status, result = validate_appscale_credentials('bwayne', 'batman', 'batman')
12
+ assert status
13
+ assert_equal result, ''
14
+
15
+ status, result = validate_appscale_credentials(nil, 'batman', 'batman')
16
+ assert !status
17
+ assert result.include?('username')
18
+
19
+ status, result = validate_appscale_credentials('bwayne', nil, 'batman')
20
+ assert !status
21
+ assert result.include?('password')
22
+
23
+ status, result = validate_appscale_credentials('bwayne', 'batman', nil)
24
+ assert !status
25
+ assert result.include?('password')
26
+
27
+ status, result = validate_appscale_credentials('bwayne', 'batman', 'robin')
28
+ assert !status
29
+
30
+ status, result = validate_appscale_credentials('bwayne', 'robin', 'robin')
31
+ assert !status
32
+ end
33
+
34
+ def test_validate_yaml
35
+ yaml = <<EOS
36
+ ---
37
+ :controller: 192.168.1.2
38
+ :servers:
39
+ - 192.168.1.3
40
+ - 192.168.1.4
41
+ - 192.168.1.5
42
+ EOS
43
+ status, result = validate_yaml(yaml)
44
+ assert status
45
+
46
+ yaml = <<EOS
47
+ :master: 192.168.1.2
48
+ :appengine:
49
+ - 192.168.1.3
50
+ - 192.168.1.4
51
+ :database:
52
+ - 192.168.1.5
53
+ EOS
54
+ status, result = validate_yaml(yaml)
55
+ assert status
56
+
57
+ yaml = <<EOS
58
+ ---
59
+ :controller: 192.168.1.2
60
+ EOS
61
+ status, result = validate_yaml(yaml)
62
+ assert status
63
+
64
+ yaml = <<EOS
65
+ ---
66
+ :appengine: 192.168.1.2
67
+ EOS
68
+ status, result = validate_yaml(yaml)
69
+ assert !status
70
+
71
+ yaml = <<EOS
72
+ ---
73
+ :controller: 192.168.1.2
74
+ :bogus_role:
75
+ - 192.168.1.3
76
+ - 192.168.1.4
77
+ - 192.168.1.5
78
+ EOS
79
+ status, result = validate_yaml(yaml)
80
+ assert !status
81
+
82
+ status, result = validate_yaml(nil)
83
+ assert !status
84
+ status, result = validate_yaml("")
85
+ assert !status
86
+ end
87
+
88
+ def test_validate_ec2_cluster_settings
89
+ status, result = validate_ec2_cluster_settings("1", "1", "ami-123456")
90
+ assert status
91
+
92
+ status, result = validate_ec2_cluster_settings(nil, "1", "ami-123456")
93
+ assert !status
94
+ status, result = validate_ec2_cluster_settings("", "1", "ami-123456")
95
+ assert !status
96
+ status, result = validate_ec2_cluster_settings("1", nil, "ami-123456")
97
+ assert !status
98
+ status, result = validate_ec2_cluster_settings("1", "", "ami-123456")
99
+ assert !status
100
+ status, result = validate_ec2_cluster_settings("1", "1", nil)
101
+ assert !status
102
+ status, result = validate_ec2_cluster_settings("1", "1", "")
103
+ assert !status
104
+ status, result = validate_ec2_cluster_settings("0", "1", "ami-123456")
105
+ assert !status
106
+ status, result = validate_ec2_cluster_settings("1", "0", "ami-123456")
107
+ assert !status
108
+ status, result = validate_ec2_cluster_settings("5", "4", "ami-123456")
109
+ assert !status
110
+ status, result = validate_ec2_cluster_settings("-1", "1", "ami-123456")
111
+ assert !status
112
+ status, result = validate_ec2_cluster_settings("1", "-1", "ami-123456")
113
+ assert !status
114
+ status, result = validate_ec2_cluster_settings("a", "b", "ami-123456")
115
+ assert !status
116
+ end
117
+
118
+ def test_validate_ec2_credentials
119
+ status, result = validate_ec2_credentials("", "batcowl", "batmobile", "gotham-city")
120
+ assert !status
121
+ status, result = validate_ec2_credentials(nil, "batcowl", "batmobile", "gotham-city")
122
+ assert !status
123
+ status, result = validate_ec2_credentials("bwayne", "", "batmobile", "gotham-city")
124
+ assert !status
125
+ status, result = validate_ec2_credentials("bwayne", nil, "batmobile", "gotham-city")
126
+ assert !status
127
+ status, result = validate_ec2_credentials("bwayne", "batcowl", "", "gotham-city")
128
+ assert !status
129
+ status, result = validate_ec2_credentials("bwayne", "batcowl", nil, "gotham-city")
130
+ assert !status
131
+ status, result = validate_ec2_credentials("bwayne", "batcowl", "batmobile", "")
132
+ assert !status
133
+ status, result = validate_ec2_credentials("bwayne", "batcowl", "batmobile", nil)
134
+ assert !status
135
+
136
+ flexmock(CommonFunctions).should_receive(:shell).times(3).
137
+ and_return("", "AuthFailure", "us-east-1")
138
+ status, result = validate_ec2_credentials("bwayne", "batcowl", "batmobile", "us-east-1")
139
+ assert !status
140
+ status, result = validate_ec2_credentials("bwayne", "batcowl", "batmobile", "us-east-1")
141
+ assert !status
142
+ status, result = validate_ec2_credentials("bwayne", "batcowl", "batmobile", "us-east-1")
143
+ assert status
144
+ end
145
+
146
+ def test_validate_ec2_certificate_uploads
147
+ status, result = validate_ec2_certificate_uploads("", "dummy", "dummy")
148
+ assert !status
149
+ status, result = validate_ec2_certificate_uploads(nil, "dummy", "dummy")
150
+ assert !status
151
+ status, result = validate_ec2_certificate_uploads("bwayne", nil, "dummy")
152
+ assert !status
153
+ status, result = validate_ec2_certificate_uploads("bwayne", "dummy", nil)
154
+ assert !status
155
+ end
156
+
157
+ def test_redirect_standard_io
158
+ timestamp = 12345678
159
+ redirect_standard_io(timestamp) {
160
+ do_stuff
161
+ }
162
+ log = File.join(File.expand_path(File.dirname(__FILE__)), "..",
163
+ "logs", "deploy-#{timestamp}.log")
164
+ file = File.new(log, "r")
165
+ counter = 0
166
+ while (line = file.gets)
167
+ assert_equal("Doing stuff", line.chomp)
168
+ counter += 1
169
+ end
170
+ file.close
171
+
172
+ assert_equal(1, counter)
173
+
174
+ File.delete(log)
175
+ end
176
+
177
+ def test_locking
178
+ assert lock
179
+ assert !lock
180
+ assert locked?
181
+ assert unlock
182
+ assert !unlock
183
+ assert !locked?
184
+ end
185
+
186
+ def test_deploy_on_virtual_cluster
187
+ flexmock(AppScaleTools).should_receive(:add_keypair).and_return {
188
+ puts "Generating keys"
189
+ }
190
+ flexmock(AppScaleTools).should_receive(:run_instances).and_return do
191
+ 5.times do |i|
192
+ puts "Deploying..."
193
+ sleep(1)
194
+ end
195
+ end
196
+
197
+ params = { :keyname => "appscale" }
198
+ result = deploy_on_virtual_cluster(params, {}, {})
199
+ assert result[0]
200
+
201
+ output = `kill -0 #{result[2]}`
202
+ assert output.length == 0
203
+ assert locked?
204
+
205
+ puts "Waiting 10 seconds for the mock Xen deployment tasks to complete"
206
+ sleep(10)
207
+
208
+ assert !locked?
209
+ log = File.join(File.expand_path(File.dirname(__FILE__)), "..",
210
+ "logs", "deploy-#{result[1]}.log")
211
+ assert File.exist?(log)
212
+ File.delete(log)
213
+ end
214
+
215
+ def test_deploy_on_ec2
216
+ flexmock(AppScaleTools).should_receive(:run_instances).and_return do
217
+ 5.times do |i|
218
+ puts "Deploying..."
219
+ sleep(1)
220
+ end
221
+ end
222
+
223
+ params = { :keyname => "appscale",
224
+ :region => "us-east-1",
225
+ :access_key => "access_key",
226
+ :secret_key => "secret_key",
227
+ :username => "username"
228
+ }
229
+ result = deploy_on_ec2(params, {}, 12345678)
230
+ assert result[0]
231
+
232
+ output = `kill -0 #{result[2]}`
233
+ assert output.length == 0
234
+ assert locked?
235
+
236
+ puts "Waiting 10 seconds for the mock EC2 deployment tasks to complete"
237
+ sleep(10)
238
+
239
+ assert !locked?
240
+ log = File.join(File.expand_path(File.dirname(__FILE__)), "..",
241
+ "logs", "deploy-#{result[1]}.log")
242
+ assert File.exist?(log)
243
+ File.delete(log)
244
+ end
245
+
246
+ def do_stuff
247
+ puts "Doing stuff"
248
+ end
249
+
250
+ end
@@ -22,7 +22,7 @@
22
22
  <div class="control-group">
23
23
  <label class="control-label" for="root_password">Root Password <span class="required">*</span></label>
24
24
  <div class="controls">
25
- <input name="root_password" id="root_password" type="password" placeholder="Confirm Password"/>
25
+ <input name="root_password" id="root_password" type="password" placeholder="Enter Password"/>
26
26
  <span class="help-block">
27
27
  Unix/Linux root passwords for the machines/VMs. The same root password
28
28
  should work on all the machines/VMs specified in ips.yaml.
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appscake
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 0
9
- - 2
10
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
11
10
  platform: ruby
12
11
  authors:
13
12
  - Hiranya Jayathilaka
@@ -15,24 +14,51 @@ autorequire: appscake_utils
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2012-09-28 00:00:00 Z
17
+ date: 2012-10-12 00:00:00 -07:00
18
+ default_executable: appscake
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: net-ssh
21
+ name: appscale-tools
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
24
  requirements:
26
25
  - - ">="
27
26
  - !ruby/object:Gem::Version
28
- hash: 23
27
+ segments:
28
+ - 1
29
+ - 6
30
+ - 0
31
+ version: 1.6.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: net-ssh
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
29
41
  segments:
30
42
  - 2
31
43
  - 6
32
44
  - 0
33
45
  version: 2.6.0
34
46
  type: :runtime
35
- version_requirements: *id001
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: sinatra
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 3
58
+ - 2
59
+ version: 1.3.2
60
+ type: :runtime
61
+ version_requirements: *id003
36
62
  description: " AppsCake provides a pretty web interface that can be used to deploy\n AppScale over machines in Xen, KVM, Amazon EC2, or Eucalyptus. In\n short, it makes deploying AppScale a piece of cake!\n"
37
63
  email: appscale_community@googlegroups.com
38
64
  executables:
@@ -42,39 +68,42 @@ extensions: []
42
68
  extra_rdoc_files: []
43
69
 
44
70
  files:
45
- - README.txt
46
- - LICENSE.txt
47
- - Rakefile
48
- - lib/appscake_utils.rb
49
71
  - bin/appscake
50
72
  - certificates/cert-appscake.pem
51
73
  - certificates/pk-appscake.pem
52
- - views/error.erb
74
+ - generate_coverage.sh
75
+ - lib/appscake_utils.rb
76
+ - LICENSE.txt
77
+ - public/bootstrap/css/bootstrap-responsive.css
78
+ - public/bootstrap/css/bootstrap-responsive.min.css
79
+ - public/bootstrap/css/bootstrap.css
80
+ - public/bootstrap/css/bootstrap.min.css
81
+ - public/bootstrap/img/glyphicons-halflings-white.png
82
+ - public/bootstrap/img/glyphicons-halflings.png
83
+ - public/bootstrap/js/bootstrap.js
84
+ - public/bootstrap/js/bootstrap.min.js
85
+ - public/css/bootstrap-responsive.css
86
+ - public/css/bootstrap-responsive.min.css
87
+ - public/css/bootstrap.css
88
+ - public/css/bootstrap.min.css
89
+ - public/img/glyphicons-halflings-white.png
90
+ - public/img/glyphicons-halflings.png
91
+ - public/js/appscake_validator.js
92
+ - public/js/bootstrap.js
93
+ - public/js/bootstrap.min.js
94
+ - public/js/jquery-1.7.1.min.js
95
+ - public/js/jquery.validate.min.js
96
+ - Rakefile
97
+ - README.txt
98
+ - test/tc_appscake_utils.rb
53
99
  - views/_common.erb
100
+ - views/_ec2.erb
54
101
  - views/_virtual.erb
102
+ - views/error.erb
55
103
  - views/index.erb
56
104
  - views/success.erb
57
- - views/_ec2.erb
58
105
  - views/view_log.erb
59
- - public/bootstrap/js/bootstrap.js
60
- - public/bootstrap/js/bootstrap.min.js
61
- - public/bootstrap/img/glyphicons-halflings-white.png
62
- - public/bootstrap/img/glyphicons-halflings.png
63
- - public/bootstrap/css/bootstrap-responsive.css
64
- - public/bootstrap/css/bootstrap.min.css
65
- - public/bootstrap/css/bootstrap.css
66
- - public/bootstrap/css/bootstrap-responsive.min.css
67
- - public/js/jquery.validate.min.js
68
- - public/js/jquery-1.7.1.min.js
69
- - public/js/bootstrap.js
70
- - public/js/appscake_validator.js
71
- - public/js/bootstrap.min.js
72
- - public/img/glyphicons-halflings-white.png
73
- - public/img/glyphicons-halflings.png
74
- - public/css/bootstrap-responsive.css
75
- - public/css/bootstrap.min.css
76
- - public/css/bootstrap.css
77
- - public/css/bootstrap-responsive.min.css
106
+ has_rdoc: true
78
107
  homepage: http://appscale.cs.ucsb.edu
79
108
  licenses: []
80
109
 
@@ -84,27 +113,23 @@ rdoc_options: []
84
113
  require_paths:
85
114
  - lib
86
115
  required_ruby_version: !ruby/object:Gem::Requirement
87
- none: false
88
116
  requirements:
89
117
  - - ">="
90
118
  - !ruby/object:Gem::Version
91
- hash: 3
92
119
  segments:
93
120
  - 0
94
121
  version: "0"
95
122
  required_rubygems_version: !ruby/object:Gem::Requirement
96
- none: false
97
123
  requirements:
98
124
  - - ">="
99
125
  - !ruby/object:Gem::Version
100
- hash: 3
101
126
  segments:
102
127
  - 0
103
128
  version: "0"
104
129
  requirements: []
105
130
 
106
131
  rubyforge_project:
107
- rubygems_version: 1.8.24
132
+ rubygems_version: 1.3.6
108
133
  signing_key:
109
134
  specification_version: 3
110
135
  summary: A web interface to the AppScale command-line tools.