stackfu 0.1.0
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/CHANGELOG +24 -0
- data/Manifest +118 -0
- data/README +0 -0
- data/README.md +218 -0
- data/Rakefile +73 -0
- data/bin/stackfu +10 -0
- data/lib/stackfu/api_hooks.rb +17 -0
- data/lib/stackfu/app.rb +69 -0
- data/lib/stackfu/commands/command.rb +127 -0
- data/lib/stackfu/commands/config_command.rb +43 -0
- data/lib/stackfu/commands/deploy_command.rb +144 -0
- data/lib/stackfu/commands/dump_command.rb +101 -0
- data/lib/stackfu/commands/generate_command.rb +107 -0
- data/lib/stackfu/commands/help_command.rb +28 -0
- data/lib/stackfu/commands/list_command.rb +26 -0
- data/lib/stackfu/commands/publish_command.rb +108 -0
- data/lib/stackfu/commands/server_command.rb +124 -0
- data/lib/stackfu/helpers/providers_credentials.rb +82 -0
- data/lib/stackfu/helpers/rendering.rb +201 -0
- data/lib/stackfu/operating_systems.rb +30 -0
- data/lib/stackfu.rb +88 -0
- data/stackfu-installer/config/01-controls.yml +17 -0
- data/stackfu-installer/config/02-requirements.yml +3 -0
- data/stackfu-installer/config/03-scripts.yml +16 -0
- data/stackfu-installer/config/04-validations.yml +3 -0
- data/stackfu-installer/script/dotfiles_installation.sh.erb +22 -0
- data/stackfu-installer/script/github_credentials_setup.sh.erb +31 -0
- data/stackfu-installer/script/nginx_and_passenger.sh.erb +83 -0
- data/stackfu-installer/script/redis_installation.sh.erb +33 -0
- data/stackfu-installer/script/resque_installation.sh.erb +7 -0
- data/stackfu-installer/script/ruby_environment.sh.erb +20 -0
- data/stackfu-installer/script/stackfu.sh.erb +114 -0
- data/stackfu-installer/stack.yml +5 -0
- data/stackfu.gemspec +60 -0
- data/templates/01-controls.yml.erb +31 -0
- data/templates/02-requirements.yml.erb +26 -0
- data/templates/03-scripts.yml.erb +34 -0
- data/templates/04-validations.yml.erb +17 -0
- data/templates/script.sh.erb +7 -0
- data/templates/stack.yml.erb +17 -0
- data/test/fixtures/add_server_error +7 -0
- data/test/fixtures/deployment_add +7 -0
- data/test/fixtures/deployment_add_error +8 -0
- data/test/fixtures/deployments +7 -0
- data/test/fixtures/logs +7 -0
- data/test/fixtures/logs_partial +7 -0
- data/test/fixtures/plugin_add +6 -0
- data/test/fixtures/plugin_add_error +8 -0
- data/test/fixtures/plugin_deployment_add +7 -0
- data/test/fixtures/plugin_not_found +7 -0
- data/test/fixtures/plugin_unauthorized +8 -0
- data/test/fixtures/plugins +7 -0
- data/test/fixtures/plugins_by_name +7 -0
- data/test/fixtures/plugins_by_name_other +7 -0
- data/test/fixtures/plugins_empty +7 -0
- data/test/fixtures/plugins_multiple +7 -0
- data/test/fixtures/providers +7 -0
- data/test/fixtures/providers_servers +7 -0
- data/test/fixtures/server_add +6 -0
- data/test/fixtures/server_add_dupe +7 -0
- data/test/fixtures/server_add_error +7 -0
- data/test/fixtures/server_delete +7 -0
- data/test/fixtures/server_delete_error +7 -0
- data/test/fixtures/servers +7 -0
- data/test/fixtures/servers_by_name +7 -0
- data/test/fixtures/servers_empty +8 -0
- data/test/fixtures/servers_not_found +26 -0
- data/test/fixtures/servers_unauthorized +8 -0
- data/test/fixtures/servers_webbynode +7 -0
- data/test/fixtures/stack/stackfu-installer/config/01-controls.yml +22 -0
- data/test/fixtures/stack/stackfu-installer/config/02-requirements.yml +1 -0
- data/test/fixtures/stack/stackfu-installer/config/03-scripts.yml +23 -0
- data/test/fixtures/stack/stackfu-installer/config/04-validations.yml +1 -0
- data/test/fixtures/stack/stackfu-installer/script/dotfiles_installation.sh.erb +22 -0
- data/test/fixtures/stack/stackfu-installer/script/github_credentials_setup.sh.erb +31 -0
- data/test/fixtures/stack/stackfu-installer/script/nginx_and_passenger.sh.erb +83 -0
- data/test/fixtures/stack/stackfu-installer/script/redis_installation.sh.erb +33 -0
- data/test/fixtures/stack/stackfu-installer/script/resque_installation.sh.erb +7 -0
- data/test/fixtures/stack/stackfu-installer/script/ruby_environment.sh.erb +20 -0
- data/test/fixtures/stack/stackfu-installer/script/stackfu.sh.erb +76 -0
- data/test/fixtures/stack/stackfu-installer/stack.yml +5 -0
- data/test/fixtures/stack_add +6 -0
- data/test/fixtures/stack_add_error +8 -0
- data/test/fixtures/stack_add_error_dupe +8 -0
- data/test/fixtures/stack_adds_by_name +7 -0
- data/test/fixtures/stack_delete_not_found +7 -0
- data/test/fixtures/stacks +7 -0
- data/test/fixtures/stacks_by_name +7 -0
- data/test/fixtures/stacks_by_name_other +7 -0
- data/test/fixtures/stacks_empty +7 -0
- data/test/fixtures/stacks_multiple +7 -0
- data/test/fixtures/stacks_not_found +7 -0
- data/test/fixtures/stacks_realworld +7 -0
- data/test/fixtures/stacks_stackfu-installer +7 -0
- data/test/fixtures/stacks_unauthorized +8 -0
- data/test/fixtures/stacks_with_controls +0 -0
- data/test/fixtures/users +7 -0
- data/test/fixtures/users_no_credentials +7 -0
- data/test/fixtures/users_update +6 -0
- data/test/stack.yml +26 -0
- data/test/support/custom_matchers.rb +69 -0
- data/test/support/fixtures.rb +98 -0
- data/test/support/io_stub.rb +10 -0
- data/test/support/web_fixtures.rb +91 -0
- data/test/test_helper.rb +186 -0
- data/test/unit/commands/test_command.rb +112 -0
- data/test/unit/commands/test_config_command.rb +92 -0
- data/test/unit/commands/test_deploy_command.rb +303 -0
- data/test/unit/commands/test_dump_command.rb +155 -0
- data/test/unit/commands/test_generate_command.rb +112 -0
- data/test/unit/commands/test_help_command.rb +33 -0
- data/test/unit/commands/test_list_command.rb +63 -0
- data/test/unit/commands/test_publish_command.rb +265 -0
- data/test/unit/commands/test_server_command.rb +259 -0
- data/test/unit/helpers/test_rendering.rb +141 -0
- data/test/unit/test_array.rb +26 -0
- data/test/unit/test_provider.rb +14 -0
- data/test/unit/test_stackfu.rb +27 -0
- metadata +311 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module StackFu
|
|
2
|
+
module ProvidersCredentials
|
|
3
|
+
def add_webbynode_credentials(user)
|
|
4
|
+
while true
|
|
5
|
+
puts ""
|
|
6
|
+
puts "Enter your Webbynode API credentials below (or type 'help' for more information or 'abort' to abort)"
|
|
7
|
+
|
|
8
|
+
login = ask("Webbynode Login:")
|
|
9
|
+
|
|
10
|
+
unless login.try(:downcase) == "abort" or login.try(:downcase) == "help"
|
|
11
|
+
token = ask("Webbynode Token:")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
credentials = [login || "", token || ""].map(&:downcase)
|
|
15
|
+
|
|
16
|
+
if credentials.include?('help')
|
|
17
|
+
puts ""
|
|
18
|
+
puts "== Webbynode StackFu integration ==".foreground(:green).bright
|
|
19
|
+
puts ""
|
|
20
|
+
puts "In order to allow StackFu to integrate itself with Webbynode, you need to provide the email address you use to login into Webbynode Manager and your API token."
|
|
21
|
+
puts ""
|
|
22
|
+
puts "This can be easily done by visiting your '#{"Account".foreground(:cyan)}' area in Webbynode Manager. On the box where your summary is presented, copy the 'API Token:' field content."
|
|
23
|
+
puts ""
|
|
24
|
+
puts "If you need further information, visit #{"http://stackfu.com/faq/webbynode-api-integration".underline} for a complete walkthrough of this process."
|
|
25
|
+
|
|
26
|
+
elsif credentials.include?('abort')
|
|
27
|
+
|
|
28
|
+
puts "Aborted adding server."
|
|
29
|
+
return false
|
|
30
|
+
|
|
31
|
+
else
|
|
32
|
+
user.settings.webbynode_login = login
|
|
33
|
+
user.settings.webbynode_token = token
|
|
34
|
+
|
|
35
|
+
if user.save
|
|
36
|
+
puts ""
|
|
37
|
+
puts "Webbynode credentials saved."
|
|
38
|
+
else
|
|
39
|
+
puts "Error: #{user.errors.full_messages.to_s}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
return true
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def add_slicehost_credentials(user)
|
|
48
|
+
while true
|
|
49
|
+
puts ""
|
|
50
|
+
puts "Enter your Slicehost API password (or type 'help' for more information or 'abort' to abort): "
|
|
51
|
+
|
|
52
|
+
token = ask("")
|
|
53
|
+
|
|
54
|
+
unless ['help', 'abort'].include? token.downcase
|
|
55
|
+
user.settings.slicehost_token = token
|
|
56
|
+
if user.save
|
|
57
|
+
puts ""
|
|
58
|
+
puts "Slicehost credentials saved."
|
|
59
|
+
else
|
|
60
|
+
puts "Error: #{user.errors.full_messages.to_s}"
|
|
61
|
+
end
|
|
62
|
+
return true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if token.downcase == 'abort'
|
|
66
|
+
puts ""
|
|
67
|
+
puts "Aborted adding server."
|
|
68
|
+
return false
|
|
69
|
+
else
|
|
70
|
+
puts ""
|
|
71
|
+
puts "== Slicehost StackFu integration ==".foreground(:green).bright
|
|
72
|
+
puts ""
|
|
73
|
+
puts "In order to allow StackFu to integrate itself with Slicehost, you need to enabled your API Access and provide us your API Password."
|
|
74
|
+
puts ""
|
|
75
|
+
puts "This can be easily done by visiting your '#{"Account > API Access".foreground(:cyan)}' area in Slicehost manager."
|
|
76
|
+
puts ""
|
|
77
|
+
puts "If you need further information, visit #{"http://stackfu.com/faq/slicehost-api-integration".underline} for a complete walkthrough of this process."
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
module StackFu
|
|
2
|
+
module Rendering
|
|
3
|
+
LEFT_MARGIN = 2
|
|
4
|
+
|
|
5
|
+
def warning(question)
|
|
6
|
+
puts "== WARNING ==".foreground(:red)
|
|
7
|
+
agree(question)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def fill_values_from_options(stack, options)
|
|
11
|
+
params = {}
|
|
12
|
+
|
|
13
|
+
stack.controls.each do |c|
|
|
14
|
+
if (opt = options[c.name.to_sym])
|
|
15
|
+
case c._type
|
|
16
|
+
when "Textbox"
|
|
17
|
+
params[c.name] = opt if opt
|
|
18
|
+
|
|
19
|
+
when "Numericbox"
|
|
20
|
+
begin
|
|
21
|
+
params[c.name] = Float(opt)
|
|
22
|
+
rescue ArgumentError
|
|
23
|
+
error "Value for #{c.name} should be numeric"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
params
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def render_target(params, target, options)
|
|
34
|
+
max_length = target.controls.map { |c| c.label.size }.max
|
|
35
|
+
|
|
36
|
+
target.controls.each do |c|
|
|
37
|
+
unless params[c.name]
|
|
38
|
+
case c._type
|
|
39
|
+
when "Textbox"
|
|
40
|
+
params[c.name] = ask(" #{c.label.rjust(max_length)}: ")
|
|
41
|
+
|
|
42
|
+
when "Numericbox"
|
|
43
|
+
params[c.name] = ask(" #{c.label.rjust(max_length)}: ", Integer)
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
params
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def done(message, more_info=nil)
|
|
53
|
+
puts "#{"Success:".foreground(:green).bright} #{message}"
|
|
54
|
+
puts "\n#{more_info}" if more_info
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def error(message, more_info=nil)
|
|
58
|
+
puts "#{"Error:".foreground(:red).bright} #{message}"
|
|
59
|
+
puts "\n#{more_info}" if more_info
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def menu_for(name, collection, convert=false)
|
|
63
|
+
choice = choose do |menu|
|
|
64
|
+
menu.header = "Available #{name.pluralize}"
|
|
65
|
+
menu.prompt = "\nSelect the #{name}:"
|
|
66
|
+
menu.shell = true
|
|
67
|
+
|
|
68
|
+
collection.each { |p| menu.choice(p.name) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
if convert
|
|
72
|
+
collection.select { |i| i.name == choice }.first.id
|
|
73
|
+
else
|
|
74
|
+
choice
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def table(opts)
|
|
79
|
+
collection = opts[:collection]
|
|
80
|
+
display = opts[:display]
|
|
81
|
+
if (classes = opts[:class]).is_a?(Array)
|
|
82
|
+
single = {}
|
|
83
|
+
plural = {}
|
|
84
|
+
opts[:class].each do |kls|
|
|
85
|
+
single[kls] = kls.name.demodulize.humanize.downcase
|
|
86
|
+
plural[kls] = single[kls].pluralize
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
single = opts[:class].name.demodulize.humanize.downcase
|
|
90
|
+
plural = single.pluralize
|
|
91
|
+
end
|
|
92
|
+
labels = opts[:labels]
|
|
93
|
+
main_column = opts[:main_column]
|
|
94
|
+
ascii = opts[:ansi] == false
|
|
95
|
+
header = opts[:header]
|
|
96
|
+
|
|
97
|
+
if collection.empty?
|
|
98
|
+
msg = opts[:empty]
|
|
99
|
+
msg ||= "No #{plural}."
|
|
100
|
+
return msg
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
columns = display.inject([]) do |arr, item|
|
|
104
|
+
label = labels ? labels[item] : item.to_s.titleize
|
|
105
|
+
arr << { :name => item.to_s, :label => label }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
display.each_with_index do |column, i|
|
|
109
|
+
max_value_size = collection.map do |item|
|
|
110
|
+
value = block_given? ? yield(item)[i] : item.send(column)
|
|
111
|
+
value.to_s.size
|
|
112
|
+
end.max
|
|
113
|
+
|
|
114
|
+
size = [max_value_size, column.to_s.size].max
|
|
115
|
+
columns[i][:size] = size
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
title = header || if classes.is_a?(Array)
|
|
119
|
+
counter = Hash.new(0)
|
|
120
|
+
collection.each do |item|
|
|
121
|
+
counter[item.class] += 1
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
parts = []
|
|
125
|
+
collection.map(&:class).uniq.each do |k|
|
|
126
|
+
v = counter[k]
|
|
127
|
+
parts << "#{v} #{v > 1 ? plural[k] : single[k]}"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
"Listing #{parts.to_phrase}:\n"
|
|
131
|
+
else
|
|
132
|
+
"Listing #{collection.size} #{collection.size > 1 ? plural : single}:\n"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
table = []
|
|
136
|
+
if ascii
|
|
137
|
+
table << columns.inject("") { |str, col| str << "#{col[:label].ljust(col[:size])} " }
|
|
138
|
+
table << columns.inject("") { |str, col| str << "#{"-" * (col[:size]+1)} " }
|
|
139
|
+
else
|
|
140
|
+
# table << columns.inject("") { |str, col| str << "#{col[:label].titleize.ljust(col[:size]+1).underline.foreground(:yellow)} " }
|
|
141
|
+
table << columns.inject("") { |str, col| str << "#{col[:label].ljust(col[:size]+1).underline.foreground(:yellow)} " }
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
collection.each do |item|
|
|
145
|
+
values = block_given? ? yield(item) : nil
|
|
146
|
+
|
|
147
|
+
idx = 0
|
|
148
|
+
table << columns.inject("") do |str, col|
|
|
149
|
+
if block_given?
|
|
150
|
+
value = values[idx]
|
|
151
|
+
idx += 1
|
|
152
|
+
else
|
|
153
|
+
value = item.send(col[:name])
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
just_method = value.is_a?(Numeric) ? :rjust : :ljust
|
|
157
|
+
|
|
158
|
+
if ascii
|
|
159
|
+
str << "#{value.to_s.send(just_method, col[:size])} "
|
|
160
|
+
else
|
|
161
|
+
if col[:name].to_sym == main_column
|
|
162
|
+
str << "#{value.to_s.send(just_method, col[:size]).foreground(:blue)} "
|
|
163
|
+
else
|
|
164
|
+
str << "#{value.to_s.send(just_method, col[:size])} "
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
table.map! { |line| "#{" " * LEFT_MARGIN}#{line}"}
|
|
171
|
+
|
|
172
|
+
[title, table].flatten.join("\n")
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def spinner(&code)
|
|
176
|
+
chars = %w{ | / - \\ }
|
|
177
|
+
|
|
178
|
+
result = nil
|
|
179
|
+
t = Thread.new {
|
|
180
|
+
result = code.call
|
|
181
|
+
}
|
|
182
|
+
while t.alive?
|
|
183
|
+
print chars[0]
|
|
184
|
+
STDOUT.flush
|
|
185
|
+
|
|
186
|
+
sleep 0.1
|
|
187
|
+
|
|
188
|
+
print "\b"
|
|
189
|
+
STDOUT.flush
|
|
190
|
+
|
|
191
|
+
chars.push chars.shift
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
print " \b"
|
|
195
|
+
STDOUT.flush
|
|
196
|
+
|
|
197
|
+
t.join
|
|
198
|
+
result
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module StackFu
|
|
2
|
+
module OperatingSystems
|
|
3
|
+
OperatingSystems = [
|
|
4
|
+
:arch_2009, :centos_52, :centos_53, :gentoo_2008, :debian_50,
|
|
5
|
+
:fedora_10, :ubuntu_804, :ubuntu_810, :ubuntu_904
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
FriendlyNames = {
|
|
9
|
+
"ArchLinux 2009" => :arch_2009,
|
|
10
|
+
"Arch 2009" => :arch_2009,
|
|
11
|
+
"Centos 5.2" => :centos_52,
|
|
12
|
+
"Centos 5.3" => :centos_53,
|
|
13
|
+
"Gentoo 2008" => :gentoo_2008,
|
|
14
|
+
"Debian 5.0" => :debian_50,
|
|
15
|
+
"Fedora 10" => :fedora_10,
|
|
16
|
+
"Ubuntu 8.04" => :ubuntu_804,
|
|
17
|
+
"Ubuntu 8.10" => :ubuntu_810,
|
|
18
|
+
"Ubuntu 9.04" => :ubuntu_904
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
def convert_os(friendly)
|
|
22
|
+
StackFu::OperatingSystems::FriendlyNames[friendly] or raise "Unknown OS: #{friendly}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def os_name(os_key)
|
|
26
|
+
os_key = os_key.try(:to_sym)
|
|
27
|
+
StackFu::OperatingSystems::FriendlyNames.index(os_key) or raise "Unknown OS: #{os_key}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/stackfu.rb
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
|
|
3
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
|
4
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
|
5
|
+
|
|
6
|
+
gem 'activesupport', '>=2.3.5'
|
|
7
|
+
gem 'activeresource', '>=2.3.5'
|
|
8
|
+
gem 'rainbow', '>=1.0.4'
|
|
9
|
+
gem 'highline', '>=1.5.1'
|
|
10
|
+
gem 'httparty', '>=0.4.5'
|
|
11
|
+
|
|
12
|
+
begin
|
|
13
|
+
require 'active_resource'
|
|
14
|
+
require 'active_support'
|
|
15
|
+
rescue LoadError
|
|
16
|
+
require 'activeresource'
|
|
17
|
+
require 'activesupport'
|
|
18
|
+
end
|
|
19
|
+
require 'rainbow'
|
|
20
|
+
require 'highline/import'
|
|
21
|
+
require 'httparty'
|
|
22
|
+
require 'fileutils'
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /mswin/
|
|
26
|
+
rescue LoadError
|
|
27
|
+
puts "Hint: if you want to make your output better in windows, install the win32console gem:"
|
|
28
|
+
puts " gem install win32console"
|
|
29
|
+
puts ""
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
dir = Pathname(__FILE__).dirname.expand_path + 'stackfu'
|
|
33
|
+
|
|
34
|
+
require "#{dir}/helpers/rendering"
|
|
35
|
+
require "#{dir}/helpers/providers_credentials"
|
|
36
|
+
|
|
37
|
+
require "#{dir}/operating_systems"
|
|
38
|
+
require "#{dir}/api_hooks"
|
|
39
|
+
require "#{dir}/app"
|
|
40
|
+
|
|
41
|
+
require "#{dir}/commands/command"
|
|
42
|
+
require "#{dir}/commands/help_command"
|
|
43
|
+
require "#{dir}/commands/server_command"
|
|
44
|
+
require "#{dir}/commands/config_command"
|
|
45
|
+
require "#{dir}/commands/generate_command"
|
|
46
|
+
require "#{dir}/commands/publish_command"
|
|
47
|
+
require "#{dir}/commands/list_command"
|
|
48
|
+
require "#{dir}/commands/deploy_command"
|
|
49
|
+
require "#{dir}/commands/dump_command"
|
|
50
|
+
|
|
51
|
+
module StackFu
|
|
52
|
+
VERSION = '0.0.1'
|
|
53
|
+
API = "http://api.stackfu.com"
|
|
54
|
+
CONFIG_FILE = "#{ENV['HOME']}/.stackfu"
|
|
55
|
+
|
|
56
|
+
include StackFu::OperatingSystems
|
|
57
|
+
|
|
58
|
+
module Exceptions
|
|
59
|
+
class UnknownCommand < StandardError; end
|
|
60
|
+
class InvalidCommand < StandardError; end
|
|
61
|
+
class InvalidSubcommand < StandardError; end
|
|
62
|
+
class InvalidParameter < StandardError; end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
OpenStruct.__send__(:define_method, :id) { @table[:id] || self.object_id }
|
|
67
|
+
|
|
68
|
+
class Array
|
|
69
|
+
def to_phrase
|
|
70
|
+
self.to_sentence(:words_connector => ", ", :last_word_connector => " and ")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def to_structs
|
|
74
|
+
self.map { |hash| OpenStruct.new(hash) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_params
|
|
78
|
+
self.map { |item| item.to_s.upcase }.join(" ")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class String
|
|
83
|
+
def truncate_words(length = 30, end_string = '…')
|
|
84
|
+
words = self.split()
|
|
85
|
+
words[0..(length-1)].join(' ') + (words.length > length ? end_string : '')
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
controls:
|
|
3
|
+
- label: Github User
|
|
4
|
+
name: github_user
|
|
5
|
+
type: Textbox
|
|
6
|
+
- label: Github Token
|
|
7
|
+
name: github_token
|
|
8
|
+
type: Textbox
|
|
9
|
+
- label: User Name
|
|
10
|
+
name: user_name
|
|
11
|
+
type: Textbox
|
|
12
|
+
- label: User Email
|
|
13
|
+
name: user_email
|
|
14
|
+
type: Textbox
|
|
15
|
+
- label: Ssh Passphrase
|
|
16
|
+
name: ssh_passphrase
|
|
17
|
+
type: Textbox
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
scripts:
|
|
3
|
+
- file: github_credentials_setup
|
|
4
|
+
description: GitHub Credentials Setup
|
|
5
|
+
- file: dotfiles_installation
|
|
6
|
+
description: Dotfiles Installation
|
|
7
|
+
- file: ruby_environment
|
|
8
|
+
description: Ruby Environment
|
|
9
|
+
- file: redis_installation
|
|
10
|
+
description: Redis Installation
|
|
11
|
+
- file: resque_installation
|
|
12
|
+
description: Resque Installation
|
|
13
|
+
- file: nginx_and_passenger
|
|
14
|
+
description: Nginx and Passenger
|
|
15
|
+
- file: stackfu
|
|
16
|
+
description: StackFu
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#
|
|
2
|
+
# install_dotfiles.sh
|
|
3
|
+
# Sun Nov 22 20:46:43 -0200 2009
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
if ! which git>/dev/null; then
|
|
7
|
+
apt-get install -y git-core
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
apt-get install -y zsh
|
|
11
|
+
apt-get install -y ruby
|
|
12
|
+
apt-get install -y mercurial
|
|
13
|
+
apt-get install -y build-essential
|
|
14
|
+
apt-get install -y vim
|
|
15
|
+
|
|
16
|
+
git clone git@github.com:fcoury/dotfiles.git bin
|
|
17
|
+
/root/bin/install-vcprompt
|
|
18
|
+
cd /root/bin/dotfiles
|
|
19
|
+
./install
|
|
20
|
+
|
|
21
|
+
sed -i s:/bin/bash:/bin/zsh:g /etc/passwd
|
|
22
|
+
echo "export PATH=/root/bin:$PATH" > /root/.private_profile
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#
|
|
2
|
+
# install_github.sh
|
|
3
|
+
# Sun Nov 22 20:46:43 -0200 2009
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
apt-get update
|
|
7
|
+
apt-get install -y git-core
|
|
8
|
+
|
|
9
|
+
key="$HOME/.ssh/id_rsa"
|
|
10
|
+
pubkey="$key.pub"
|
|
11
|
+
if [ ! -f "$pubkey" ]; then
|
|
12
|
+
ssh-keygen -t rsa -N "<%= ssh_passphrase %>" -f $key
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
gitconfig="$HOME/.gitconfig"
|
|
16
|
+
if [ ! -f "$gitconfig" ]; then
|
|
17
|
+
git config --global github.user <%= github_user %>
|
|
18
|
+
git config --global github.token <%= github_token %>
|
|
19
|
+
|
|
20
|
+
git config --global user.name <%= user_name %>
|
|
21
|
+
git config --global user.email <%= user_email %>
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
key="$HOME/.ssh/id_rsa"
|
|
25
|
+
pubkey="$key.pub"
|
|
26
|
+
key_contents=`cat $pubkey`
|
|
27
|
+
|
|
28
|
+
curl --silent -F "login=<%= github_user %>" -F "token=<%= github_token %>" \
|
|
29
|
+
https://github.com/api/v2/json/user/key/add -F "key=$key_contents"
|
|
30
|
+
|
|
31
|
+
ssh -o "StrictHostKeyChecking no" git@github.com || true
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#
|
|
2
|
+
# install_nginx_passenger.sh
|
|
3
|
+
# Sun Nov 22 20:46:43 -0200 2009
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
export PATH=/usr/lib/ruby/gems/1.8/gems/passenger-2.2.7/bin:$PATH
|
|
7
|
+
|
|
8
|
+
apt-get install -y zlib1g-dev libssl-dev
|
|
9
|
+
|
|
10
|
+
gem install passenger
|
|
11
|
+
passenger-install-nginx-module --auto --auto-download --prefix=/opt/nginx
|
|
12
|
+
|
|
13
|
+
echo '#! /bin/sh
|
|
14
|
+
|
|
15
|
+
### BEGIN INIT INFO
|
|
16
|
+
# Provides: nginx
|
|
17
|
+
# Required-Start: $all
|
|
18
|
+
# Required-Stop: $all
|
|
19
|
+
# Default-Start: 2 3 4 5
|
|
20
|
+
# Default-Stop: 0 1 6
|
|
21
|
+
# Short-Description: starts the nginx web server
|
|
22
|
+
# Description: starts nginx using start-stop-daemon
|
|
23
|
+
### END INIT INFO
|
|
24
|
+
|
|
25
|
+
PATH=/opt/nginx/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
|
26
|
+
DAEMON=/opt/nginx/sbin/nginx
|
|
27
|
+
NAME=nginx
|
|
28
|
+
DESC=nginx
|
|
29
|
+
|
|
30
|
+
test -x $DAEMON || exit 0
|
|
31
|
+
|
|
32
|
+
# Include nginx defaults if available
|
|
33
|
+
if [ -f /etc/default/nginx ] ; then
|
|
34
|
+
. /etc/default/nginx
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
set -e
|
|
38
|
+
|
|
39
|
+
. /lib/lsb/init-functions
|
|
40
|
+
|
|
41
|
+
case "$1" in
|
|
42
|
+
start)
|
|
43
|
+
echo -n "Starting $DESC: "
|
|
44
|
+
start-stop-daemon --start --quiet --pidfile /opt/nginx/logs/$NAME.pid \
|
|
45
|
+
--exec $DAEMON -- $DAEMON_OPTS || true
|
|
46
|
+
echo "$NAME."
|
|
47
|
+
;;
|
|
48
|
+
stop)
|
|
49
|
+
echo -n "Stopping $DESC: "
|
|
50
|
+
start-stop-daemon --stop --quiet --pidfile /opt/nginx/logs/$NAME.pid \
|
|
51
|
+
--exec $DAEMON || true
|
|
52
|
+
echo "$NAME."
|
|
53
|
+
;;
|
|
54
|
+
restart|force-reload)
|
|
55
|
+
echo -n "Restarting $DESC: "
|
|
56
|
+
start-stop-daemon --stop --quiet --pidfile \
|
|
57
|
+
/opt/nginx/logs/$NAME.pid --exec $DAEMON || true
|
|
58
|
+
sleep 1
|
|
59
|
+
start-stop-daemon --start --quiet --pidfile \
|
|
60
|
+
/opt/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true
|
|
61
|
+
echo "$NAME."
|
|
62
|
+
;;
|
|
63
|
+
reload)
|
|
64
|
+
echo -n "Reloading $DESC configuration: "
|
|
65
|
+
start-stop-daemon --stop --signal HUP --quiet --pidfile /opt/nginx/logs/$NAME.pid \
|
|
66
|
+
--exec $DAEMON || true
|
|
67
|
+
echo "$NAME."
|
|
68
|
+
;;
|
|
69
|
+
status)
|
|
70
|
+
status_of_proc -p /opt/nginx/logs/$NAME.pid "$DAEMON" nginx && exit 0 || exit $?
|
|
71
|
+
;;
|
|
72
|
+
*)
|
|
73
|
+
N=/etc/init.d/$NAME
|
|
74
|
+
echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
|
|
75
|
+
exit 1
|
|
76
|
+
;;
|
|
77
|
+
esac
|
|
78
|
+
|
|
79
|
+
exit 0
|
|
80
|
+
' > /etc/init.d/nginx
|
|
81
|
+
|
|
82
|
+
chmod +x /etc/init.d/nginx
|
|
83
|
+
/etc/init.d/nginx start
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#
|
|
2
|
+
# install_redis.sh
|
|
3
|
+
# Sun Nov 22 20:46:43 -0200 2009
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
apt-get install -y cronolog
|
|
7
|
+
gem install rspec
|
|
8
|
+
|
|
9
|
+
# cd /usr/src
|
|
10
|
+
# git clone git://github.com/ezmobius/redis-rb.git
|
|
11
|
+
# cd redis-rb
|
|
12
|
+
# rake redis:install
|
|
13
|
+
# # rake install
|
|
14
|
+
|
|
15
|
+
cd /usr/src
|
|
16
|
+
wget -q http://redis.googlecode.com/files/redis-1.02.tar.gz
|
|
17
|
+
tar xzvf redis-1.02.tar.gz
|
|
18
|
+
cd redis-1.02/
|
|
19
|
+
make -j
|
|
20
|
+
cp redis.conf /etc
|
|
21
|
+
ln -s /usr/src/redis-1.02/redis-server /usr/bin/redis-server
|
|
22
|
+
ln -s /usr/src/redis-1.02/redis-cli /usr/bin/redis-cli
|
|
23
|
+
|
|
24
|
+
echo "
|
|
25
|
+
daemonize no
|
|
26
|
+
logfile stdout" >> /etc/redis.conf
|
|
27
|
+
echo "nohup /usr/bin/redis-server /etc/redis.conf | /usr/bin/cronolog /var/log/redis/redis.%Y-%m-%d.log 2>&1 &" > /etc/init.d/redis.sh
|
|
28
|
+
|
|
29
|
+
chmod +x /etc/init.d/redis.sh
|
|
30
|
+
|
|
31
|
+
#setsid bash -c "nohup /usr/bin/redis-server /etc/redis.conf | /usr/bin/cronolog /var/log/redis/redis.%Y-%m-%d.log 2>&1 &"
|
|
32
|
+
|
|
33
|
+
sed -i "s/loglevel debug/loglevel notice/g" /etc/redis.conf
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#
|
|
2
|
+
# install_dotfiles.sh
|
|
3
|
+
# Sun Nov 22 20:46:43 -0200 2009
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
apt-get install -y build-essential
|
|
7
|
+
apt-get install -y ruby irb1.8 ruby1.8-dev libreadline-ruby1.8 libruby1.8 ruby1.8 irb libopenssl-ruby libopenssl-ruby1.8
|
|
8
|
+
|
|
9
|
+
cd /usr/src
|
|
10
|
+
wget http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz
|
|
11
|
+
tar xvzf rubygems-1.3.5.tgz
|
|
12
|
+
cd rubygems-1.3.5
|
|
13
|
+
sudo ruby setup.rb
|
|
14
|
+
|
|
15
|
+
sudo ln -s /usr/bin/gem1.8 /usr/local/bin/gem
|
|
16
|
+
sudo ln -s /usr/bin/ruby1.8 /usr/local/bin/ruby
|
|
17
|
+
sudo ln -s /usr/bin/irb1.8 /usr/local/bin/irb
|
|
18
|
+
|
|
19
|
+
gem install rake
|
|
20
|
+
ln -s /usr/lib/ruby/1.8/bin/rake /usr/local/bin/rake
|