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 +14 -8
- data/Rakefile +20 -2
- data/bin/appscake +21 -4
- data/generate_coverage.sh +3 -0
- data/lib/appscake_utils.rb +63 -63
- data/test/tc_appscake_utils.rb +250 -0
- data/views/_virtual.erb +1 -1
- metadata +64 -39
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
|
10
|
-
|
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
|
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
|
-
|
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
|
-
|
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://
|
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.
|
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
|
data/bin/appscake
CHANGED
@@ -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__), "
|
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
|
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
|
data/lib/appscake_utils.rb
CHANGED
@@ -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
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
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
|
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.
|
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("
|
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
|
-
|
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[:
|
261
|
+
key_file = File.expand_path("~/.appscale/#{params[:virtual_keyname]}")
|
256
262
|
if File.exists?(key_file)
|
257
|
-
puts "AppScale key '#{params[:
|
263
|
+
puts "AppScale key '#{params[:virtual_keyname]}' found on the disk. Reusing..."
|
258
264
|
else
|
259
|
-
puts "AppScale key '#{params[:
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
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
|
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
|
data/views/_virtual.erb
CHANGED
@@ -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="
|
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
|
-
|
5
|
-
prerelease:
|
4
|
+
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
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-
|
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:
|
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
|
-
|
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: *
|
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
|
-
-
|
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
|
-
|
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.
|
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.
|