stackfu 0.1.7 → 0.1.8
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/Manifest +3 -7
- data/Rakefile +1 -1
- data/lib/stackfu/commands/dump_command.rb +38 -4
- data/lib/stackfu/commands/publish_command.rb +173 -75
- data/lib/stackfu.rb +12 -3
- data/spec/fixtures/scripts/pwned.json +12 -0
- data/spec/fixtures/scripts/pwned1.json +12 -0
- data/spec/stackfu/commands/dump_command_spec.rb +69 -1
- data/spec/stackfu/commands/publish_command_spec.rb +117 -0
- data/stackfu.gemspec +3 -3
- data/templates/02-requirements.yml.erb +2 -1
- data/templates/04-validations.yml.erb +2 -1
- data/templates/stack.yml.erb +1 -0
- metadata +7 -12
- data/firewall/config/01-controls.yml +0 -5
- data/firewall/config/02-requirements.yml +0 -4
- data/firewall/config/03-executions.yml +0 -6
- data/firewall/config/04-validations.yml +0 -4
- data/firewall/executables/configure_ufw.sh.erb +0 -9
- data/firewall/executables/install_ufw.sh.erb +0 -7
- data/firewall/script.yml +0 -8
data/Manifest
CHANGED
@@ -5,13 +5,6 @@ README.md
|
|
5
5
|
Rakefile
|
6
6
|
autotest/discover.rb
|
7
7
|
bin/stackfu
|
8
|
-
firewall/config/01-controls.yml
|
9
|
-
firewall/config/02-requirements.yml
|
10
|
-
firewall/config/03-executions.yml
|
11
|
-
firewall/config/04-validations.yml
|
12
|
-
firewall/executables/configure_ufw.sh.erb
|
13
|
-
firewall/executables/install_ufw.sh.erb
|
14
|
-
firewall/script.yml
|
15
8
|
lib/stackfu.rb
|
16
9
|
lib/stackfu/api_hooks.rb
|
17
10
|
lib/stackfu/app.rb
|
@@ -49,6 +42,8 @@ spec/fixtures/scripts/mongo/deploy.json
|
|
49
42
|
spec/fixtures/scripts/none.json
|
50
43
|
spec/fixtures/scripts/not_found.json
|
51
44
|
spec/fixtures/scripts/password.json
|
45
|
+
spec/fixtures/scripts/pwned.json
|
46
|
+
spec/fixtures/scripts/pwned1.json
|
52
47
|
spec/fixtures/scripts/script_not_found.json
|
53
48
|
spec/fixtures/servers/all.json
|
54
49
|
spec/fixtures/servers/cannot_deploy.json
|
@@ -78,6 +73,7 @@ stackfu-installer/script/resque_installation.sh.erb
|
|
78
73
|
stackfu-installer/script/ruby_environment.sh.erb
|
79
74
|
stackfu-installer/script/stackfu.sh.erb
|
80
75
|
stackfu-installer/stack.yml
|
76
|
+
stackfu.gemspec
|
81
77
|
templates/01-controls.yml.erb
|
82
78
|
templates/02-requirements.yml.erb
|
83
79
|
templates/03-executions.yml.erb
|
data/Rakefile
CHANGED
@@ -12,7 +12,13 @@ module StackFu::Commands
|
|
12
12
|
|
13
13
|
script = spinner {
|
14
14
|
begin
|
15
|
-
|
15
|
+
if script_name.include?('/')
|
16
|
+
user_name, script_name = script_name.split('/')
|
17
|
+
user = User.new(:id => user_name)
|
18
|
+
Script.new(user.get(script_name))
|
19
|
+
else
|
20
|
+
Script.find(script_name)
|
21
|
+
end
|
16
22
|
rescue ActiveResource::ResourceNotFound
|
17
23
|
end
|
18
24
|
}
|
@@ -36,9 +42,37 @@ module StackFu::Commands
|
|
36
42
|
|
37
43
|
if script.respond_to?(:controls)
|
38
44
|
controls = map script.controls, "controls" do |c|
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
options = {}
|
46
|
+
validations = {}
|
47
|
+
validation_messages = {}
|
48
|
+
|
49
|
+
if c.respond_to?(:options) and !c.options.empty?
|
50
|
+
options = {
|
51
|
+
"options" => c.options
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
if c.respond_to?(:validations) and !c.validations.empty?
|
56
|
+
validations = {
|
57
|
+
"validations" => c.validations.attributes.to_hash
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
if c.respond_to?(:validation_messages) and !c.validation_messages.empty?
|
62
|
+
validation_messages = {
|
63
|
+
"validation_messages" => c.validation_messages.attributes.to_hash
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
required = 'false'
|
68
|
+
if c.respond_to?(:required)
|
69
|
+
required = c.required.to_s
|
70
|
+
end
|
71
|
+
|
72
|
+
{ "name" => c.name,
|
73
|
+
"label" => c.label,
|
74
|
+
"type" => c._type,
|
75
|
+
"required" => required }.merge(validations).merge(validation_messages).merge(options)
|
42
76
|
end
|
43
77
|
else
|
44
78
|
controls = []
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module StackFu::Commands
|
2
|
+
class CheckFailed < StandardError; end
|
3
|
+
|
2
4
|
class PublishCommand < Command
|
3
5
|
include StackFu::ApiHooks
|
4
6
|
aliases :pub
|
@@ -32,99 +34,101 @@ module StackFu::Commands
|
|
32
34
|
"Make sure you have a file named 'stack.yml', 'plugin.yml' or use 'stackfu generate' for creating a new stack."
|
33
35
|
end
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
+
silently do
|
38
|
+
begin
|
39
|
+
stack_spec = read_and_validate(what)
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
if @errors.keys.any?
|
42
|
+
error format_error
|
43
|
+
return
|
44
|
+
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
%w[controls requirements executions validations].each_with_index do |item, i|
|
47
|
+
if (yaml = read("config/0#{i+1}-#{item}.yml"))
|
48
|
+
yaml.gsub!("type:", "_type:")
|
49
|
+
if (from_yaml = YAML.load(yaml))
|
50
|
+
if item == 'requirements' or item == 'validations'
|
51
|
+
buffer = []
|
52
|
+
from_yaml[item].each do |itm|
|
53
|
+
itm["params"] = { "data" => itm.delete("data") }
|
54
|
+
buffer << itm
|
55
|
+
end
|
56
|
+
from_yaml[item] = buffer
|
52
57
|
end
|
53
|
-
from_yaml[item] = buffer
|
54
|
-
end
|
55
58
|
|
56
|
-
|
59
|
+
stack_spec[item == "scripts" ? "executions" : item] = from_yaml[item]
|
60
|
+
end
|
57
61
|
end
|
58
62
|
end
|
59
|
-
end
|
60
|
-
|
61
|
-
unless stack_spec["executions"].present?
|
62
|
-
error "To publish a #{what} you have to define at least one execution.",
|
63
|
-
"Take a look at the executions descriptor file config/03-executions.yml for more information.\nYou can also use 'stackfu generate stack_name script_name:script' command to auto-generate a sample execution."
|
64
|
-
return false
|
65
|
-
end
|
66
|
-
|
67
|
-
return unless stack_spec["executions"].each do |script|
|
68
|
-
template = "executables/#{script["file"]}.sh.erb"
|
69
63
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
break false
|
64
|
+
unless stack_spec["executions"].present?
|
65
|
+
error "To publish a #{what} you have to define at least one execution.",
|
66
|
+
"Take a look at the executions descriptor file config/03-executions.yml for more information.\nYou can also use 'stackfu generate stack_name script_name:script' command to auto-generate a sample execution."
|
67
|
+
return false
|
75
68
|
end
|
69
|
+
|
70
|
+
return unless stack_spec["executions"].each do |script|
|
71
|
+
template = "executables/#{script["file"]}.sh.erb"
|
76
72
|
|
77
|
-
|
78
|
-
|
73
|
+
begin
|
74
|
+
script["body"] = read(template)
|
75
|
+
rescue Errno::ENOENT
|
76
|
+
error "The template file for the script '#{script["description"]}' was not found.", "This script has an executable called '#{script["description"]}', and the template for it should be in a file called executables/#{script["file"]}.sh.erb."
|
77
|
+
break false
|
78
|
+
end
|
79
79
|
|
80
|
-
|
81
|
-
item_class.format = :json
|
82
|
-
|
83
|
-
begin
|
84
|
-
stack = item_class.find(stack_spec["name"])
|
85
|
-
rescue ActiveResource::ResourceNotFound
|
86
|
-
rescue NoMethodError
|
87
|
-
if $!.message =~ /closed\?/
|
88
|
-
raise Errno::ECONNREFUSED
|
89
|
-
else
|
90
|
-
raise
|
80
|
+
true
|
91
81
|
end
|
92
|
-
|
82
|
+
|
83
|
+
item_class = StackFu::ApiHooks.const_get("#{what.to_s.classify}")
|
84
|
+
item_class.format = :json
|
93
85
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
86
|
+
begin
|
87
|
+
stack = item_class.find(stack_spec["name"])
|
88
|
+
rescue ActiveResource::ResourceNotFound
|
89
|
+
rescue NoMethodError
|
90
|
+
if $!.message =~ /closed\?/
|
91
|
+
raise Errno::ECONNREFUSED
|
100
92
|
else
|
101
|
-
|
102
|
-
return false
|
93
|
+
raise
|
103
94
|
end
|
104
95
|
end
|
96
|
+
|
97
|
+
if stack
|
98
|
+
unless options[:update]
|
99
|
+
if agree("You already have a #{what} named #{stack_spec["name"]}. Do you want to update it?")
|
100
|
+
puts ""
|
101
|
+
puts "Tip: Next time you can avoid this question using 'stack pub --update'."
|
102
|
+
puts ""
|
103
|
+
else
|
104
|
+
puts "Aborted."
|
105
|
+
return false
|
106
|
+
end
|
107
|
+
end
|
105
108
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
begin
|
110
|
+
item_class.delete(stack.name)
|
111
|
+
rescue ActiveResource::ResourceNotFound
|
112
|
+
puts "There was a problem updating your #{what}. Please report this problem at support@stackfu.com or try again in a few minutes."
|
113
|
+
return
|
114
|
+
end
|
111
115
|
end
|
112
|
-
end
|
113
116
|
|
114
|
-
|
117
|
+
puts "Publishing #{what} #{stack_spec["name"]}..."
|
115
118
|
|
116
|
-
|
119
|
+
stack = item_class.new(stack_spec)
|
117
120
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
121
|
+
if publish(stack)
|
122
|
+
done "#{what.to_s.titleize} #{stack.name} published."
|
123
|
+
else
|
124
|
+
error "Could not publish your stack: #{stack.errors.full_messages.to_s}"
|
125
|
+
end
|
126
|
+
rescue ActiveResource::ServerError
|
127
|
+
error "#{$!.message}"
|
128
|
+
rescue Errno::ENOENT
|
129
|
+
error "There was an error opening your file descriptor"
|
130
|
+
raise
|
122
131
|
end
|
123
|
-
rescue ActiveResource::ServerError
|
124
|
-
error "#{$!.message}"
|
125
|
-
rescue Errno::ENOENT
|
126
|
-
error "There was an error opening your file descriptor"
|
127
|
-
raise
|
128
132
|
end
|
129
133
|
end
|
130
134
|
|
@@ -137,6 +141,21 @@ module StackFu::Commands
|
|
137
141
|
false
|
138
142
|
end
|
139
143
|
|
144
|
+
def add_error(error)
|
145
|
+
(@errors[@file]||=[]) << error.gsub(/'(.*)'/, '\1'.foreground(:blue).bright)
|
146
|
+
end
|
147
|
+
|
148
|
+
def check2(file)
|
149
|
+
@file = file
|
150
|
+
begin
|
151
|
+
block_given? ? yield : false
|
152
|
+
true
|
153
|
+
rescue CheckFailed
|
154
|
+
(@errors[file]||=[]) << $!.message.gsub(/'(.*)'/, '\1'.foreground(:blue).bright)
|
155
|
+
false
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
140
159
|
def read_and_check(yml)
|
141
160
|
begin
|
142
161
|
return YAML.load(read(yml))
|
@@ -194,11 +213,82 @@ module StackFu::Commands
|
|
194
213
|
end
|
195
214
|
end
|
196
215
|
|
216
|
+
def validate_control_type(item)
|
217
|
+
check('config/01-controls.yml', "invalid type '#{item["type"]}' for control #{item["name"].try(:foreground, :blue).try(:bright)}") {
|
218
|
+
%w(Textbox Numericbox Password Radio Combobox).include? item['type']
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
def option_needed?(item)
|
223
|
+
item['type'] == 'Radio' or item['type'] == 'Combobox'
|
224
|
+
end
|
225
|
+
|
226
|
+
def validate_options_presence(item)
|
227
|
+
check('config/01-controls.yml', "missing options for #{item["type"]} control #{item["name"].try(:foreground, :blue).try(:bright)}") {
|
228
|
+
if option_needed?(item)
|
229
|
+
!item['options'].nil?
|
230
|
+
else
|
231
|
+
true
|
232
|
+
end
|
233
|
+
}
|
234
|
+
end
|
235
|
+
|
236
|
+
def validate_options_format(item)
|
237
|
+
check('config/01-controls.yml', "invalid options format for #{item["type"]} control #{item["name"].try(:foreground, :blue).try(:bright)}") {
|
238
|
+
if option_needed?(item)
|
239
|
+
if !item['options'].nil?
|
240
|
+
begin
|
241
|
+
valid = true
|
242
|
+
if item['options'].is_a?(Array)
|
243
|
+
item['options'].each do |option|
|
244
|
+
valid = false unless option.is_a?(Array) && option.size == 2
|
245
|
+
end
|
246
|
+
else
|
247
|
+
valid = false
|
248
|
+
end
|
249
|
+
valid
|
250
|
+
rescue ArgumentError
|
251
|
+
false
|
252
|
+
end
|
253
|
+
else
|
254
|
+
true
|
255
|
+
end
|
256
|
+
else
|
257
|
+
true
|
258
|
+
end
|
259
|
+
}
|
260
|
+
end
|
261
|
+
|
262
|
+
def allows_validation?(item)
|
263
|
+
['Textbox', 'Numericbox', 'Password'].include? item['type']
|
264
|
+
end
|
265
|
+
|
266
|
+
ValidationTypes = %w(matches required minlength maxlength rangelength min max range email url date dateISO number digits equalTo)
|
267
|
+
|
268
|
+
def valid_validation?(type, value)
|
269
|
+
ValidationTypes.include?(type)
|
270
|
+
end
|
271
|
+
|
272
|
+
def validate_validations_format(item)
|
273
|
+
check2('config/01-controls.yml') do
|
274
|
+
return unless allows_validation?(item) and !(vals = item['validations']).nil?
|
275
|
+
|
276
|
+
error = "invalid validations format for #{item["type"]} #{blue(item["name"])}"
|
277
|
+
raise CheckFailed, error unless vals.is_a?(Hash)
|
278
|
+
|
279
|
+
vals.each_pair do |type, value|
|
280
|
+
message = "invalid validation type for #{item["type"]} #{blue(item["name"])}: #{red(type)}"
|
281
|
+
add_error message unless valid_validation?(type, value)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
197
286
|
def validate_controls
|
198
287
|
validate_spec '01', 'controls', 'name', ['name', 'type'] do |item, i|
|
199
|
-
|
200
|
-
|
201
|
-
|
288
|
+
validate_control_type(item) &&
|
289
|
+
validate_options_presence(item) &&
|
290
|
+
validate_options_format(item) &&
|
291
|
+
validate_validations_format(item)
|
202
292
|
end
|
203
293
|
end
|
204
294
|
|
@@ -234,5 +324,13 @@ module StackFu::Commands
|
|
234
324
|
|
235
325
|
def load_stack
|
236
326
|
end
|
327
|
+
|
328
|
+
def blue(s)
|
329
|
+
s.try(:foreground, :blue).try(:bright)
|
330
|
+
end
|
331
|
+
|
332
|
+
def red(s)
|
333
|
+
s.try(:foreground, :red)
|
334
|
+
end
|
237
335
|
end
|
238
336
|
end
|
data/lib/stackfu.rb
CHANGED
@@ -49,10 +49,11 @@ require "#{dir}/commands/list_command"
|
|
49
49
|
require "#{dir}/commands/deploy_command"
|
50
50
|
require "#{dir}/commands/dump_command"
|
51
51
|
|
52
|
+
ActiveSupport::Deprecation.silenced = true
|
53
|
+
|
52
54
|
module StackFu
|
53
|
-
VERSION = '0.1.
|
54
|
-
API = "https://beta.stackfu.com"
|
55
|
-
# API = "http://localhost:3000"
|
55
|
+
VERSION = '0.1.8'
|
56
|
+
API = ENV['STACKFU_ENV'] == 'development' ? "http://localhost:3000" : "https://beta.stackfu.com"
|
56
57
|
CONFIG_FILE = "#{ENV['HOME']}/.stackfu"
|
57
58
|
|
58
59
|
include StackFu::OperatingSystems
|
@@ -101,3 +102,11 @@ end
|
|
101
102
|
# return http
|
102
103
|
# end
|
103
104
|
# end
|
105
|
+
|
106
|
+
def silently(&block)
|
107
|
+
warn_level = $VERBOSE
|
108
|
+
$VERBOSE = nil
|
109
|
+
result = block.call
|
110
|
+
$VERBOSE = warn_level
|
111
|
+
result
|
112
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
X-Ua-Compatible: IE=Edge,chrome=1
|
3
|
+
Etag: "178597adbc4a0ad53d5f17fce7b06016"
|
4
|
+
Connection: Keep-Alive
|
5
|
+
Content-Type: application/json; charset=utf-8
|
6
|
+
Date: Thu, 14 Oct 2010 21:34:02 GMT
|
7
|
+
Server: WEBrick/1.3.1 (Ruby/1.8.7/2009-12-24)
|
8
|
+
X-Runtime: 1.295549
|
9
|
+
Content-Length: 984
|
10
|
+
Cache-Control: max-age=0, private, must-revalidate
|
11
|
+
|
12
|
+
{"controls":[{"required":true,"name":"grade","label":"Grade","_id":"4cb776acd489e8ee82000045","_type":"Textbox","validations":{"maxlength":1,"matches":"^[A|B|C]$"},"validation_messages":{"maxlength":"must have 1 or less characters!","matches":"must be A, B or C"}},{"required":false,"name":"school","label":"School","_id":"4cb776acd489e8ee82000046","_type":"Radio","options":[[1,"one"]]}],"name":"pwned","slug":"pwned","created_at":"2010-10-14T21:31:24Z","deploy_count":0,"updated_at":"2010-10-14T21:31:24Z","_id":"4cb776acd489e8ee82000048","tags":[],"watching_users_count":1,"user_id":"4c8585167d7c425923000003","executions":[{"body":"# \n# mydear.sh\n# Thu Oct 14 11:08:19 -0300 2010\n#\n\n# TODO: Replace the contents of this file with \"Mydear\"\necho [<%= Time.now %>] Installing -- Mydear\n","_id":"4cb776acd489e8ee82000047","_type":"Executable","file":"mydear","description":"Mydear"}],"description":"Add your description here","watching_user_ids":["4c8585167d7c425923000003"]}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
X-Ua-Compatible: IE=Edge,chrome=1
|
3
|
+
Etag: "178597adbc4a0ad53d5f17fce7b06016"
|
4
|
+
Connection: Keep-Alive
|
5
|
+
Content-Type: application/json; charset=utf-8
|
6
|
+
Date: Thu, 14 Oct 2010 21:34:02 GMT
|
7
|
+
Server: WEBrick/1.3.1 (Ruby/1.8.7/2009-12-24)
|
8
|
+
X-Runtime: 1.295549
|
9
|
+
Content-Length: 984
|
10
|
+
Cache-Control: max-age=0, private, must-revalidate
|
11
|
+
|
12
|
+
{"controls":[{"required":true,"name":"grade","label":"Grade","_id":"4cb776acd489e8ee82000045","_type":"Textbox","validations":{"maxlength":1,"matches":"^[A|B|C]$"},"validation_messages":{"maxlength":"must have 1 or less characters!","matches":"must be A, B or C"}},{"required":false,"name":"school","label":"School","_id":"4cb776acd489e8ee82000046","_type":"Radio","options":[[1,"one"]]}],"name":"pwned","slug":"pwned","created_at":"2010-10-14T21:31:24Z","deploy_count":0,"updated_at":"2010-10-14T21:31:24Z","_id":"4cb776acd489e8ee82000048","tags":[],"watching_users_count":1,"user_id":"4c8585167d7c425923000003","executions":[{"body":"# \n# mydear.sh\n# Thu Oct 14 11:08:19 -0300 2010\n#\n\n# TODO: Replace the contents of this file with \"Mydear\"\necho [<%= Time.now %>] Installing -- Mydear\n","_id":"4cb776acd489e8ee82000047","_type":"Executable","file":"mydear","description":"Mydear"}],"description":"Add your description here","watching_user_ids":["4c8585167d7c425923000003"]}
|
@@ -24,10 +24,19 @@ describe StackFu::Commands::DumpCommand do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
context "valid script" do
|
27
|
+
before(:each) do
|
28
|
+
StackFu::Commands::DumpCommand.any_instance.tap do |cmd|
|
29
|
+
cmd.stubs(:mkdir)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
27
33
|
it "creates a directory structure that describes the stack" do
|
28
34
|
prepare :get, "/scripts/firewall.json", "/scripts/firewall.json"
|
29
35
|
|
30
|
-
StackFu::Commands::DumpCommand.any_instance.
|
36
|
+
StackFu::Commands::DumpCommand.any_instance.tap do |cmd|
|
37
|
+
cmd.expects(:directory?).with("firewall").returns(false)
|
38
|
+
cmd.stubs(:write_file)
|
39
|
+
end
|
31
40
|
|
32
41
|
command "dump firewall"
|
33
42
|
stdout.should =~ /^\tcreate firewall\//
|
@@ -43,5 +52,64 @@ describe StackFu::Commands::DumpCommand do
|
|
43
52
|
stdout.should =~ /^\tcreate firewall\/executables\/configure_ufw.sh.erb/
|
44
53
|
stdout.should =~ /^Success: Script firewall dumped/
|
45
54
|
end
|
55
|
+
|
56
|
+
it "dumps required" do
|
57
|
+
prepare :get, "/scripts/pwned.json"
|
58
|
+
|
59
|
+
StackFu::Commands::DumpCommand.any_instance.tap do |cmd|
|
60
|
+
cmd.expects(:directory?).with("pwned").returns(false)
|
61
|
+
cmd.expects(:write_file).at_least_once.with() do |name, contents|
|
62
|
+
if name == 'pwned/config/01-controls.yml'
|
63
|
+
controls = YAML.load(contents)["controls"]
|
64
|
+
|
65
|
+
grade_ctrl = controls.select { |c| c['name'] == 'grade' }.first
|
66
|
+
grade_ctrl["required"].should == 'true'
|
67
|
+
end
|
68
|
+
true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# TODO: check create file for controls
|
73
|
+
|
74
|
+
command "dump pwned"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "dumps validations" do
|
78
|
+
prepare :get, "/scripts/pwned.json"
|
79
|
+
|
80
|
+
StackFu::Commands::DumpCommand.any_instance.tap do |cmd|
|
81
|
+
cmd.expects(:directory?).with("pwned").returns(false)
|
82
|
+
cmd.expects(:write_file).at_least_once.with() do |name, contents|
|
83
|
+
if name == 'pwned/config/01-controls.yml'
|
84
|
+
controls = YAML.load(contents)["controls"]
|
85
|
+
|
86
|
+
options = controls.select { |c| c['name'] == 'school' }.first["options"]
|
87
|
+
options.should_not be_nil
|
88
|
+
|
89
|
+
grade_ctrl = controls.select { |c| c['name'] == 'grade' }.first
|
90
|
+
|
91
|
+
validations = grade_ctrl["validations"]
|
92
|
+
validations.should_not be_nil
|
93
|
+
validations.keys.size.should == 2
|
94
|
+
|
95
|
+
validations["matches"].should == "^[A|B|C]$"
|
96
|
+
validations["maxlength"].should == 1
|
97
|
+
|
98
|
+
validation_messages = grade_ctrl["validation_messages"]
|
99
|
+
|
100
|
+
validation_messages.should_not be_nil
|
101
|
+
validation_messages.keys.size.should == 2
|
102
|
+
|
103
|
+
validation_messages["matches"].should == "must be A, B or C"
|
104
|
+
validation_messages["maxlength"].should == "must have 1 or less characters!"
|
105
|
+
end
|
106
|
+
true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# TODO: check create file for controls
|
111
|
+
|
112
|
+
command "dump pwned"
|
113
|
+
end
|
46
114
|
end
|
47
115
|
end
|
@@ -123,6 +123,123 @@ describe StackFu::Commands::PublishCommand do
|
|
123
123
|
command "pub"
|
124
124
|
stdout.should =~ /missing name for control 1/
|
125
125
|
end
|
126
|
+
|
127
|
+
it "checks for misformatted validations" do
|
128
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
129
|
+
setup_one 'missing', 'config/01-controls.yml', <<-EOS
|
130
|
+
controls:
|
131
|
+
- type: Textbox
|
132
|
+
name: myscript
|
133
|
+
validations: abcdef
|
134
|
+
EOS
|
135
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
136
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
137
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
138
|
+
|
139
|
+
command "pub"
|
140
|
+
stdout.should =~ /invalid validations format for Textbox myscript/
|
141
|
+
end
|
142
|
+
|
143
|
+
it "checks for misformatted validations array" do
|
144
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
145
|
+
setup_one 'missing', 'config/01-controls.yml', <<-EOS
|
146
|
+
controls:
|
147
|
+
- type: Textbox
|
148
|
+
name: myscript
|
149
|
+
validations: [abcdef, ghij]
|
150
|
+
EOS
|
151
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
152
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
153
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
154
|
+
|
155
|
+
command "pub"
|
156
|
+
stdout.should =~ /invalid validations format for Textbox myscript/
|
157
|
+
end
|
158
|
+
|
159
|
+
it "checks for unknown validation type" do
|
160
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
161
|
+
setup_one 'missing', 'config/01-controls.yml', <<-EOS
|
162
|
+
controls:
|
163
|
+
- type: Textbox
|
164
|
+
name: myscript
|
165
|
+
validations:
|
166
|
+
popeye: olivia
|
167
|
+
charm: ok
|
168
|
+
EOS
|
169
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
170
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
171
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
172
|
+
|
173
|
+
command "pub"
|
174
|
+
stdout.should =~ /invalid validation type for Textbox myscript: popeye/
|
175
|
+
stdout.should =~ /invalid validation type for Textbox myscript: charm/
|
176
|
+
end
|
177
|
+
|
178
|
+
it "checks for missing options (Radio)" do
|
179
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
180
|
+
setup_one 'missing', 'config/01-controls.yml', 'controls: [{type: Radio, name: radio}]'
|
181
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
182
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
183
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
184
|
+
|
185
|
+
command "pub"
|
186
|
+
stdout.should =~ /missing options for Radio control radio/
|
187
|
+
end
|
188
|
+
|
189
|
+
it "checks for misformatted options (Radio)" do
|
190
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
191
|
+
setup_one 'missing', 'config/01-controls.yml', 'controls: [{type: Radio, name: radio, options: abcdef}]'
|
192
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
193
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
194
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
195
|
+
|
196
|
+
command "pub"
|
197
|
+
stdout.should =~ /invalid options format for Radio control radio/
|
198
|
+
end
|
199
|
+
|
200
|
+
it "checks for misformatted options (Radio)" do
|
201
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
202
|
+
setup_one 'missing', 'config/01-controls.yml', 'controls: [{type: Radio, name: radio, options: [one, two]}]'
|
203
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
204
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
205
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
206
|
+
|
207
|
+
command "pub"
|
208
|
+
stdout.should =~ /invalid options format for Radio control radio/
|
209
|
+
end
|
210
|
+
|
211
|
+
it "checks for missing options (Combobox)" do
|
212
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
213
|
+
setup_one 'missing', 'config/01-controls.yml', 'controls: [{type: Combobox, name: combobox}]'
|
214
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
215
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
216
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
217
|
+
|
218
|
+
command "pub"
|
219
|
+
stdout.should =~ /missing options for Combobox control combobox/
|
220
|
+
end
|
221
|
+
|
222
|
+
it "checks for misformatted options (Combobox)" do
|
223
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
224
|
+
setup_one 'missing', 'config/01-controls.yml', 'controls: [{type: Combobox, name: combobox, options: abcdef}]'
|
225
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
226
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
227
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
228
|
+
|
229
|
+
command "pub"
|
230
|
+
stdout.should =~ /invalid options format for Combobox control combobox/
|
231
|
+
end
|
232
|
+
|
233
|
+
it "checks for misformatted options (Combobox)" do
|
234
|
+
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
235
|
+
setup_one 'missing', 'config/01-controls.yml', 'controls: [{type: Combobox, name: combobox, options: [one, two]}]'
|
236
|
+
setup_one 'missing', 'config/02-requirements.yml', ''
|
237
|
+
setup_one 'missing', 'config/03-executions.yml', "executions:\n- {file: x, description: y}"
|
238
|
+
setup_one 'missing', 'config/04-validations.yml', ''
|
239
|
+
|
240
|
+
command "pub"
|
241
|
+
stdout.should =~ /invalid options format for Combobox control combobox/
|
242
|
+
end
|
126
243
|
|
127
244
|
it "checks for missing type" do
|
128
245
|
setup_one 'missing', 'script.yml', '{name: myscript, type: script}'
|
data/stackfu.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{stackfu}
|
5
|
-
s.version = "0.1.
|
5
|
+
s.version = "0.1.8"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Felipe Coury"]
|
9
|
-
s.date = %q{2010-10-
|
9
|
+
s.date = %q{2010-10-14}
|
10
10
|
s.default_executable = %q{stackfu}
|
11
11
|
s.description = %q{StackFu Backend}
|
12
12
|
s.email = %q{felipe@stackfu.com}
|
13
13
|
s.executables = ["stackfu"]
|
14
14
|
s.extra_rdoc_files = ["CHANGELOG", "README", "README.md", "bin/stackfu", "lib/stackfu.rb", "lib/stackfu/api_hooks.rb", "lib/stackfu/app.rb", "lib/stackfu/commands/command.rb", "lib/stackfu/commands/config_command.rb", "lib/stackfu/commands/deploy_command.rb", "lib/stackfu/commands/dump_command.rb", "lib/stackfu/commands/generate_command.rb", "lib/stackfu/commands/help_command.rb", "lib/stackfu/commands/list_command.rb", "lib/stackfu/commands/publish_command.rb", "lib/stackfu/commands/server_command.rb", "lib/stackfu/date_helper.rb", "lib/stackfu/helpers/providers_credentials.rb", "lib/stackfu/helpers/rendering.rb", "lib/stackfu/operating_systems.rb"]
|
15
|
-
s.files = ["CHANGELOG", "Manifest", "README", "README.md", "Rakefile", "autotest/discover.rb", "bin/stackfu", "
|
15
|
+
s.files = ["CHANGELOG", "Manifest", "README", "README.md", "Rakefile", "autotest/discover.rb", "bin/stackfu", "lib/stackfu.rb", "lib/stackfu/api_hooks.rb", "lib/stackfu/app.rb", "lib/stackfu/commands/command.rb", "lib/stackfu/commands/config_command.rb", "lib/stackfu/commands/deploy_command.rb", "lib/stackfu/commands/dump_command.rb", "lib/stackfu/commands/generate_command.rb", "lib/stackfu/commands/help_command.rb", "lib/stackfu/commands/list_command.rb", "lib/stackfu/commands/publish_command.rb", "lib/stackfu/commands/server_command.rb", "lib/stackfu/date_helper.rb", "lib/stackfu/helpers/providers_credentials.rb", "lib/stackfu/helpers/rendering.rb", "lib/stackfu/operating_systems.rb", "spec/fixtures/deployments/logs.json", "spec/fixtures/deployments/logs_end.json", "spec/fixtures/deployments/logs_failed.json", "spec/fixtures/deployments/logs_middle.json", "spec/fixtures/fcoury.json", "spec/fixtures/scripts/all.json", "spec/fixtures/scripts/create.json", "spec/fixtures/scripts/delete.json", "spec/fixtures/scripts/firewall.json", "spec/fixtures/scripts/firewall/deploy.json", "spec/fixtures/scripts/invalid/script.yml", "spec/fixtures/scripts/missing/config/01-controls.yml", "spec/fixtures/scripts/missing/config/02-requirements.yml", "spec/fixtures/scripts/missing/config/03-executions.yml", "spec/fixtures/scripts/missing/config/04-validations.yml", "spec/fixtures/scripts/missing/script.yml", "spec/fixtures/scripts/mongo.json", "spec/fixtures/scripts/mongo/deploy.json", "spec/fixtures/scripts/none.json", "spec/fixtures/scripts/not_found.json", "spec/fixtures/scripts/password.json", "spec/fixtures/scripts/pwned.json", "spec/fixtures/scripts/pwned1.json", "spec/fixtures/scripts/script_not_found.json", "spec/fixtures/servers/all.json", "spec/fixtures/servers/cannot_deploy.json", "spec/fixtures/servers/no_ip.json", "spec/fixtures/servers/none.json", "spec/fixtures/servers/not_found.json", "spec/fixtures/servers/webbynode.json", "spec/fixtures/users/fcoury.json", "spec/fixtures/users/fcoury/mongodb.json", "spec/spec_helper.rb", "spec/stackfu/api_hooks_spec.rb", "spec/stackfu/commands/deploy_command_spec.rb", "spec/stackfu/commands/dump_command_spec.rb", "spec/stackfu/commands/generate_command_spec.rb", "spec/stackfu/commands/list_command_spec.rb", "spec/stackfu/commands/publish_command_spec.rb", "spec/stackfu/rendering_spec.rb", "stackfu-installer/config/01-controls.yml", "stackfu-installer/config/02-requirements.yml", "stackfu-installer/config/03-executions.yml", "stackfu-installer/config/04-validations.yml", "stackfu-installer/script/dotfiles_installation.sh.erb", "stackfu-installer/script/github_credentials_setup.sh.erb", "stackfu-installer/script/nginx_and_passenger.sh.erb", "stackfu-installer/script/redis_installation.sh.erb", "stackfu-installer/script/resque_installation.sh.erb", "stackfu-installer/script/ruby_environment.sh.erb", "stackfu-installer/script/stackfu.sh.erb", "stackfu-installer/stack.yml", "stackfu.gemspec", "templates/01-controls.yml.erb", "templates/02-requirements.yml.erb", "templates/03-executions.yml.erb", "templates/04-validations.yml.erb", "templates/script.sh.erb", "templates/stack.yml.erb", "test/fixtures/add_server_error", "test/fixtures/deployment_add", "test/fixtures/deployment_add_error", "test/fixtures/deployments", "test/fixtures/logs", "test/fixtures/logs_partial", "test/fixtures/plugin_add", "test/fixtures/plugin_add_error", "test/fixtures/plugin_deployment_add", "test/fixtures/plugin_not_found", "test/fixtures/plugin_unauthorized", "test/fixtures/plugins", "test/fixtures/plugins_by_name", "test/fixtures/plugins_by_name_other", "test/fixtures/plugins_empty", "test/fixtures/plugins_multiple", "test/fixtures/providers", "test/fixtures/providers_servers", "test/fixtures/server_add", "test/fixtures/server_add_dupe", "test/fixtures/server_add_error", "test/fixtures/server_delete", "test/fixtures/server_delete_error", "test/fixtures/servers", "test/fixtures/servers_by_name", "test/fixtures/servers_empty", "test/fixtures/servers_not_found", "test/fixtures/servers_unauthorized", "test/fixtures/servers_webbynode", "test/fixtures/stack/stackfu-installer/config/01-controls.yml", "test/fixtures/stack/stackfu-installer/config/02-requirements.yml", "test/fixtures/stack/stackfu-installer/config/03-scripts.yml", "test/fixtures/stack/stackfu-installer/config/04-validations.yml", "test/fixtures/stack/stackfu-installer/script/dotfiles_installation.sh.erb", "test/fixtures/stack/stackfu-installer/script/github_credentials_setup.sh.erb", "test/fixtures/stack/stackfu-installer/script/nginx_and_passenger.sh.erb", "test/fixtures/stack/stackfu-installer/script/redis_installation.sh.erb", "test/fixtures/stack/stackfu-installer/script/resque_installation.sh.erb", "test/fixtures/stack/stackfu-installer/script/ruby_environment.sh.erb", "test/fixtures/stack/stackfu-installer/script/stackfu.sh.erb", "test/fixtures/stack/stackfu-installer/stack.yml", "test/fixtures/stack_add", "test/fixtures/stack_add_error", "test/fixtures/stack_add_error_dupe", "test/fixtures/stack_adds_by_name", "test/fixtures/stack_delete_not_found", "test/fixtures/stacks", "test/fixtures/stacks_by_name", "test/fixtures/stacks_by_name_other", "test/fixtures/stacks_empty", "test/fixtures/stacks_multiple", "test/fixtures/stacks_not_found", "test/fixtures/stacks_realworld", "test/fixtures/stacks_stackfu-installer", "test/fixtures/stacks_unauthorized", "test/fixtures/stacks_with_controls", "test/fixtures/users", "test/fixtures/users_no_credentials", "test/fixtures/users_update", "test/support/custom_matchers.rb", "test/support/fixtures.rb", "test/support/io_stub.rb", "test/support/web_fixtures.rb", "test/test_helper.rb", "test/unit/commands/test_command.rb", "test/unit/commands/test_config_command.rb", "test/unit/commands/test_deploy_command.rb", "test/unit/commands/test_dump_command.rb", "test/unit/commands/test_generate_command.rb", "test/unit/commands/test_help_command.rb", "test/unit/commands/test_list_command.rb", "test/unit/commands/test_publish_command.rb", "test/unit/commands/test_server_command.rb", "test/unit/helpers/test_rendering.rb", "test/unit/test_array.rb", "test/unit/test_provider.rb", "test/unit/test_stackfu.rb"]
|
16
16
|
s.homepage = %q{http://stackfu.com/cli}
|
17
17
|
s.post_install_message = %q{
|
18
18
|
--==-- StackFu - Server Deployment Engine --==--
|
data/templates/stack.yml.erb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stackfu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 8
|
10
|
+
version: 0.1.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Felipe Coury
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-14 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -133,13 +133,6 @@ files:
|
|
133
133
|
- Rakefile
|
134
134
|
- autotest/discover.rb
|
135
135
|
- bin/stackfu
|
136
|
-
- firewall/config/01-controls.yml
|
137
|
-
- firewall/config/02-requirements.yml
|
138
|
-
- firewall/config/03-executions.yml
|
139
|
-
- firewall/config/04-validations.yml
|
140
|
-
- firewall/executables/configure_ufw.sh.erb
|
141
|
-
- firewall/executables/install_ufw.sh.erb
|
142
|
-
- firewall/script.yml
|
143
136
|
- lib/stackfu.rb
|
144
137
|
- lib/stackfu/api_hooks.rb
|
145
138
|
- lib/stackfu/app.rb
|
@@ -177,6 +170,8 @@ files:
|
|
177
170
|
- spec/fixtures/scripts/none.json
|
178
171
|
- spec/fixtures/scripts/not_found.json
|
179
172
|
- spec/fixtures/scripts/password.json
|
173
|
+
- spec/fixtures/scripts/pwned.json
|
174
|
+
- spec/fixtures/scripts/pwned1.json
|
180
175
|
- spec/fixtures/scripts/script_not_found.json
|
181
176
|
- spec/fixtures/servers/all.json
|
182
177
|
- spec/fixtures/servers/cannot_deploy.json
|
@@ -206,6 +201,7 @@ files:
|
|
206
201
|
- stackfu-installer/script/ruby_environment.sh.erb
|
207
202
|
- stackfu-installer/script/stackfu.sh.erb
|
208
203
|
- stackfu-installer/stack.yml
|
204
|
+
- stackfu.gemspec
|
209
205
|
- templates/01-controls.yml.erb
|
210
206
|
- templates/02-requirements.yml.erb
|
211
207
|
- templates/03-executions.yml.erb
|
@@ -289,7 +285,6 @@ files:
|
|
289
285
|
- test/unit/test_array.rb
|
290
286
|
- test/unit/test_provider.rb
|
291
287
|
- test/unit/test_stackfu.rb
|
292
|
-
- stackfu.gemspec
|
293
288
|
has_rdoc: true
|
294
289
|
homepage: http://stackfu.com/cli
|
295
290
|
licenses: []
|
data/firewall/script.yml
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
---
|
2
|
-
name: firewall
|
3
|
-
type: script
|
4
|
-
description: |-
|
5
|
-
Set up a firewall for your server to improve security.
|
6
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
7
|
-
Praesent eget erat libero, id malesuada tortor.
|
8
|
-
Donec pharetra sapien et nulla ultricies ac pharetra neque vulputate.
|