appscake 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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.
|