Flucti-flucti-cli 0.1.16
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/LICENSE +7 -0
- data/README.mdown +24 -0
- data/Rakefile +56 -0
- data/TODO.txt +19 -0
- data/bin/flucti +4 -0
- data/flucti-cli.gemspec +46 -0
- data/lib/flucti.rb +20 -0
- data/lib/flucti/api_access.rb +56 -0
- data/lib/flucti/cli.rb +107 -0
- data/lib/flucti/parameters.rb +37 -0
- data/lib/flucti/resources.rb +41 -0
- data/lib/flucti/resources/account.rb +7 -0
- data/lib/flucti/resources/app_type.rb +18 -0
- data/lib/flucti/resources/backend.rb +28 -0
- data/lib/flucti/resources/basic_resource.rb +16 -0
- data/lib/flucti/resources/container.rb +15 -0
- data/lib/flucti/resources/db_server.rb +38 -0
- data/lib/flucti/resources/domain.rb +8 -0
- data/lib/flucti/resources/general.rb +14 -0
- data/lib/flucti/resources/mail_client.rb +7 -0
- data/lib/flucti/resources/mail_server.rb +7 -0
- data/lib/flucti/resources/port_forwarding.rb +15 -0
- data/lib/flucti/resources/port_forwarding/services +13921 -0
- data/lib/flucti/resources/ssh_details.rb +96 -0
- data/lib/flucti/resources/webserver.rb +9 -0
- data/lib/flucti/resources/website.rb +9 -0
- data/lib/flucti/tasks.rb +3 -0
- data/lib/flucti/tasks/apikey_tasks.rb +57 -0
- data/lib/flucti/tasks/apptype_tasks.rb +264 -0
- data/lib/flucti/tasks/connect_pack.rb +161 -0
- data/lib/flucti/tasks/db_tasks.rb +158 -0
- data/lib/flucti/tasks/mail_tasks.rb +104 -0
- data/lib/flucti/tasks/miscellaneous_tasks.rb +6 -0
- data/lib/flucti/tasks/progress_tasks.rb +24 -0
- data/lib/flucti/tasks/sshkey_tasks.rb +151 -0
- data/lib/flucti/tasks/vps/firewall_tasks.rb +84 -0
- data/lib/flucti/tasks/vps_tasks.rb +37 -0
- data/lib/flucti/tasks/webserver_tasks.rb +154 -0
- data/lib/flucti/tasks/website/apptype_tasks.rb +42 -0
- data/lib/flucti/tasks/website/backends/instances_tasks.rb +37 -0
- data/lib/flucti/tasks/website/backends_tasks.rb +254 -0
- data/lib/flucti/tasks/website/capfile_tasks.rb +41 -0
- data/lib/flucti/tasks/website/domains_tasks.rb +107 -0
- data/lib/flucti/tasks/website_tasks.rb +221 -0
- data/lib/flucti/utilities.rb +20 -0
- data/lib/flucti/utilities/connection_error_handling.rb +50 -0
- data/lib/flucti/utilities/core_ext.rb +35 -0
- data/lib/flucti/utilities/list_displayer.rb +57 -0
- data/lib/flucti/utilities/miscellaneous.rb +65 -0
- data/lib/flucti/utilities/progress_bar.rb +17 -0
- data/lib/flucti/utilities/table.rb +25 -0
- data/lib/flucti/utilities/task_packing.rb +10 -0
- data/lib/flucti/utilities/user_interface.rb +117 -0
- data/lib/vendor/ruby-progressbar-0.9/lib/ChangeLog +113 -0
- data/lib/vendor/ruby-progressbar-0.9/lib/progressbar.en.rd +103 -0
- data/lib/vendor/ruby-progressbar-0.9/lib/progressbar.ja.rd +100 -0
- data/lib/vendor/ruby-progressbar-0.9/lib/progressbar.rb +236 -0
- data/lib/vendor/ruby-progressbar-0.9/lib/test.rb +105 -0
- data/test/flucti/resources_test.rb +32 -0
- data/test/flucti/tasks_test.rb +28 -0
- data/test/flucti/utilities/miscellaneous_test.rb +54 -0
- data/test/flucti/utilities/table_test.rb +28 -0
- data/test/flucti/utilities/user_interface_test.rb +161 -0
- data/test/test_helper.rb +5 -0
- metadata +221 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
namespace :website do
|
|
2
|
+
namespace :capfile do
|
|
3
|
+
DESTINATION = "Capfile"
|
|
4
|
+
|
|
5
|
+
task(:default) { show }
|
|
6
|
+
|
|
7
|
+
desc <<-DESC
|
|
8
|
+
Display the content of latest Capfile without downloading it.
|
|
9
|
+
DESC
|
|
10
|
+
task :show do
|
|
11
|
+
site = website.fetch_current
|
|
12
|
+
puts_title "Capfile for site: #{site}"
|
|
13
|
+
puts site.get("/capfile.rb")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc <<-DESC
|
|
17
|
+
Download the latest Capfile for the current website.
|
|
18
|
+
DESC
|
|
19
|
+
task :download do
|
|
20
|
+
if File.exist?(DESTINATION) && !File.read(DESTINATION).blank?
|
|
21
|
+
puts_title "Backing up previous Capfile"
|
|
22
|
+
backup = Dir.tmpdir + "/#{File.basename DESTINATION}.#{Time.now.to_f}"
|
|
23
|
+
FileUtils.mv(DESTINATION, backup)
|
|
24
|
+
puts "Backup location: #{backup}"
|
|
25
|
+
end
|
|
26
|
+
puts_title "Downloading latest Capfile"
|
|
27
|
+
begin
|
|
28
|
+
File.open(DESTINATION, "w") do |f|
|
|
29
|
+
f.puts website.fetch_current!.get("/capfile.rb")
|
|
30
|
+
end
|
|
31
|
+
puts "Downloaded: %.2f KB" % [File.size(DESTINATION) / 1024.0]
|
|
32
|
+
rescue WebService::ResourceNotFound
|
|
33
|
+
puts "(No Capfile for the application type of the website.)"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def downloaded?
|
|
38
|
+
File.file?(DESTINATION)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
namespace :website do
|
|
2
|
+
namespace :domains do
|
|
3
|
+
desc <<-DESC
|
|
4
|
+
Attach a domain to the current website. This can be one of:
|
|
5
|
+
|
|
6
|
+
* A domain of your own: setup instructions will be displayed after
|
|
7
|
+
successful attachment. For example: "foobar.com".
|
|
8
|
+
|
|
9
|
+
* A free subdomain: choose one ending with ".flucti.com": immediately
|
|
10
|
+
available, setup required.
|
|
11
|
+
For example: "foobar.flucti.com".
|
|
12
|
+
|
|
13
|
+
* A subdomain of either a domain of your own or a free subdomain.
|
|
14
|
+
For example: "blog.foobar.com" or "blog.foobar.flucti.com".
|
|
15
|
+
|
|
16
|
+
* A wildcard subdomain.
|
|
17
|
+
For example: "*.foobar.com" or "*.foobar.flucti.com"
|
|
18
|
+
|
|
19
|
+
Environment variables:
|
|
20
|
+
$DOMAIN: the domain name.
|
|
21
|
+
DESC
|
|
22
|
+
task :attach do
|
|
23
|
+
site = website.fetch_current!
|
|
24
|
+
name = require_name!
|
|
25
|
+
|
|
26
|
+
domain = site.domains.build(:name => name)
|
|
27
|
+
|
|
28
|
+
examples = []
|
|
29
|
+
try_save domain do
|
|
30
|
+
puts_title("Request sent")
|
|
31
|
+
puts_long <<-INFO
|
|
32
|
+
* Domain #{q domain} has been scheduled for attachment to website
|
|
33
|
+
#{q site}.
|
|
34
|
+
INFO
|
|
35
|
+
if domain.attribute_set?(:cname_domain_name)
|
|
36
|
+
puts
|
|
37
|
+
puts_long <<-INFO
|
|
38
|
+
* For #{q domain} to point to your VPS's, you must go to your
|
|
39
|
+
registrar's control panel, clear any previous A or CNAME
|
|
40
|
+
records, and add a CNAME record to #{q domain.cname_domain_name}.
|
|
41
|
+
INFO
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
desc "Alias for `attach'."
|
|
47
|
+
task(:add) { attach }
|
|
48
|
+
|
|
49
|
+
desc <<-DESC
|
|
50
|
+
Detach a domain from the current website. By doing so, the website will
|
|
51
|
+
cease to be available at the specified domain.
|
|
52
|
+
|
|
53
|
+
Environment variables:
|
|
54
|
+
$DOMAIN: the domain name.
|
|
55
|
+
DESC
|
|
56
|
+
task :detach do
|
|
57
|
+
site = website.fetch_current!
|
|
58
|
+
name = require_name!
|
|
59
|
+
|
|
60
|
+
domain = site.domains.find(name)
|
|
61
|
+
domain.destroy
|
|
62
|
+
|
|
63
|
+
puts_title("Request sent")
|
|
64
|
+
puts "Domain #{q domain} has been scheduled for detachment from website #{q site}."
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
desc "Alias for `attach'."
|
|
68
|
+
task(:remove) { detach }
|
|
69
|
+
|
|
70
|
+
desc <<-DESC
|
|
71
|
+
List all domains that need a CNAME record. In order for the domains you
|
|
72
|
+
own to point to the VPS hosting a site, you need to declare a CNAME
|
|
73
|
+
record on the DNS server of the domains, most likely managed by the
|
|
74
|
+
registrar they have been bought from.
|
|
75
|
+
|
|
76
|
+
Please note that it can take up to 48 hours for the changes to
|
|
77
|
+
propagate.
|
|
78
|
+
|
|
79
|
+
Free subdomains don't need such a declaration since they are handled on
|
|
80
|
+
our side. That is why they are not listed. As a consequence, they are
|
|
81
|
+
functional immediately.
|
|
82
|
+
DESC
|
|
83
|
+
task :cnames do
|
|
84
|
+
site = website.fetch_current!
|
|
85
|
+
|
|
86
|
+
domains_with_cname = site.domains.select { |dom| dom.cname_domain_name }
|
|
87
|
+
|
|
88
|
+
if domains_with_cname.any?
|
|
89
|
+
puts_list(domains_with_cname, :id => false, :table => true) do |t|
|
|
90
|
+
t.col("Domain", :name)
|
|
91
|
+
t.col("CNAME", :cname_domain_name)
|
|
92
|
+
end
|
|
93
|
+
else
|
|
94
|
+
puts "No domain needs to be declared CNAME records."
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def require_name!
|
|
99
|
+
ENV["DOMAIN"] or
|
|
100
|
+
error! <<-MSG
|
|
101
|
+
The domain name to deal with must be specified by setting the
|
|
102
|
+
$DOMAIN environment variable. To list all domains currently attached
|
|
103
|
+
to the current website, run #{qcommand "website"}.
|
|
104
|
+
MSG
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
namespace :website do
|
|
2
|
+
task(:default) { status }
|
|
3
|
+
|
|
4
|
+
desc <<-DESC
|
|
5
|
+
List of all your declared websites.
|
|
6
|
+
DESC
|
|
7
|
+
task :list do
|
|
8
|
+
puts_title "Declared websites"
|
|
9
|
+
list_displayer.display(Website.all)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
desc <<-DESC
|
|
13
|
+
Display the names of all the declared websites. As opposed to
|
|
14
|
+
#{qcommand 'website:list'}, only the names are displayed, one name per
|
|
15
|
+
line. This is useful for batch processing.
|
|
16
|
+
DESC
|
|
17
|
+
task :names do
|
|
18
|
+
Website.all.each do |site|
|
|
19
|
+
puts(site.name)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
desc <<-DESC
|
|
24
|
+
Display the status of the current website. That is, whether it is declared
|
|
25
|
+
or not, and if it is, displays its details.
|
|
26
|
+
DESC
|
|
27
|
+
task :status do
|
|
28
|
+
site = fetch_current!
|
|
29
|
+
puts_title "Website in the current directory"
|
|
30
|
+
show(site, :include_status)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc "Alias for task `status'."
|
|
34
|
+
task(:show) { status }
|
|
35
|
+
|
|
36
|
+
desc <<-DESC
|
|
37
|
+
Declare the current website for subsequent deploys. This is necessary for
|
|
38
|
+
the site to be made online. That is, for our routers to direct traffic to
|
|
39
|
+
and from your VPS's.
|
|
40
|
+
|
|
41
|
+
Environment variables:
|
|
42
|
+
(optional) $SITEID: the name of the site for it to be referred to as later.
|
|
43
|
+
Default: the name the current working directory.
|
|
44
|
+
|
|
45
|
+
(optional) $TYPE: the ID or short name of the corresponding application
|
|
46
|
+
type (#{qcommand "apptype:list"} to see what stock
|
|
47
|
+
app. types are available, or #{qcommand "apptype:push"}
|
|
48
|
+
to create your own).
|
|
49
|
+
DESC
|
|
50
|
+
task :declare do
|
|
51
|
+
if site = fetch_current
|
|
52
|
+
puts "Already declared (as #{q site})"
|
|
53
|
+
next
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Find the application type
|
|
57
|
+
type =
|
|
58
|
+
if short = ENV["TYPE"]
|
|
59
|
+
AppType.all.find { |t| t.short == short } or
|
|
60
|
+
error! <<-MSG
|
|
61
|
+
Application type #{q short} does not exist. For a list of
|
|
62
|
+
available application types, run #{qcommand "apptype:list"}.
|
|
63
|
+
MSG
|
|
64
|
+
else
|
|
65
|
+
autodetect_app_type
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Prepare site for declaration
|
|
69
|
+
site = Website.new :name => name_of_current,
|
|
70
|
+
:app_type => type
|
|
71
|
+
|
|
72
|
+
# Attempt to push the declaration to the server
|
|
73
|
+
try_save site do
|
|
74
|
+
puts_title "Site declared"
|
|
75
|
+
show(site)
|
|
76
|
+
|
|
77
|
+
puts_subtitle("What to do next")
|
|
78
|
+
puts_long <<-INFO
|
|
79
|
+
1) Database connection:
|
|
80
|
+
-----------------------
|
|
81
|
+
If your site is database backed, and if you haven't done so already,
|
|
82
|
+
you should now set up a database server with #{qcommand \
|
|
83
|
+
"db:server:setup"} and modify the production database connection
|
|
84
|
+
settings accordingly in the configuration files (for example:
|
|
85
|
+
wp-config.php for a WordPress blog, config/database.yml for a Rails
|
|
86
|
+
application).
|
|
87
|
+
|
|
88
|
+
2) Backends:
|
|
89
|
+
------------
|
|
90
|
+
For your site to be online, webservers must receive requests from
|
|
91
|
+
visitors and turn to backend processes (typically PHP or Rails) to
|
|
92
|
+
process them. So there has to exist at least one webserver running,
|
|
93
|
+
and at least one backend on one of the webserver VPS's. Such an
|
|
94
|
+
architecture can be put in place by:
|
|
95
|
+
|
|
96
|
+
* Setting up an initial, minimal stack, in an automated fashion:
|
|
97
|
+
$ #{command "website:ensure_deployable"}
|
|
98
|
+
|
|
99
|
+
* or going through each step manually for finer grained control.
|
|
100
|
+
Example:
|
|
101
|
+
$ #{command "webserver:setup ON=felix"}
|
|
102
|
+
$ #{command "website:backends:add ON=felix"}
|
|
103
|
+
|
|
104
|
+
The actions of whichever option you choose can be reverted or altered
|
|
105
|
+
later.
|
|
106
|
+
|
|
107
|
+
3) Deployment:
|
|
108
|
+
--------------
|
|
109
|
+
To upload the files of your website to the backends, you can either:
|
|
110
|
+
|
|
111
|
+
* Download and run an automatically generated recipe, in the form of
|
|
112
|
+
a Capfile:
|
|
113
|
+
$ #{command "website:capfile:download"}
|
|
114
|
+
$ cap deploy:setup deploy
|
|
115
|
+
|
|
116
|
+
* Connect to each backend individually and upload the files to them.
|
|
117
|
+
For example:
|
|
118
|
+
$ #{command "website:backends:connect:details"}
|
|
119
|
+
$ scp -P 1025 -r * foo@bar.flucti.net:~/mysite/current
|
|
120
|
+
|
|
121
|
+
5) Wait:
|
|
122
|
+
--------
|
|
123
|
+
Wait a few moments for all automated actions to finish, and then your
|
|
124
|
+
site should be online at http://#{site.domains.first}:
|
|
125
|
+
$ #{command "progress"}
|
|
126
|
+
|
|
127
|
+
6) Domain:
|
|
128
|
+
----------
|
|
129
|
+
The default domain that has been attached automatically to your site
|
|
130
|
+
can be replaced by attaching your actual domain with
|
|
131
|
+
#{qcommand("website:domains:attach")} and removing the default one
|
|
132
|
+
with #{qcommand("website:domains:detach")}.
|
|
133
|
+
INFO
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
desc <<-DESC
|
|
138
|
+
Make sure the site can be deployed. For this to be the case, there has to
|
|
139
|
+
exist at least one webserver: one is set up if none is yet. Also, the
|
|
140
|
+
website has to be running on at least one of the VPS that run a webserver.
|
|
141
|
+
Failing that, the VPS with the webserver last set up is chosen as the
|
|
142
|
+
first host for the website. Those two parameters can be altered later.
|
|
143
|
+
DESC
|
|
144
|
+
task :ensure_deployable do
|
|
145
|
+
website = fetch_current!
|
|
146
|
+
|
|
147
|
+
if (count = website.backends.all.size).zero?
|
|
148
|
+
webserver.ensure_any
|
|
149
|
+
backends.add
|
|
150
|
+
else
|
|
151
|
+
puts_title "Backends present"
|
|
152
|
+
puts "There exists #{count} backends."
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
desc "Alias for task `website:backends:enter'."
|
|
157
|
+
task(:enter) { backends.enter }
|
|
158
|
+
|
|
159
|
+
desc <<-DESC
|
|
160
|
+
Delete a website and all of its backends. This will take it offline and
|
|
161
|
+
soft-clear all files stored in the backends (see #{qcommand 'website:backends:remove'}).
|
|
162
|
+
DESC
|
|
163
|
+
task :delete do
|
|
164
|
+
site = fetch_current!
|
|
165
|
+
confirm <<-WARN
|
|
166
|
+
Deleting a website will make it will:
|
|
167
|
+
|
|
168
|
+
* Cancel its declaration, making it unavailable.
|
|
169
|
+
|
|
170
|
+
* Do the equivalent of #{qcommand "website:backends:remove"} for all the
|
|
171
|
+
backends, so be sure to read the documentation of this command
|
|
172
|
+
(#{qcommand '-e website:backends:remove'}) before confirming.
|
|
173
|
+
WARN
|
|
174
|
+
site.destroy
|
|
175
|
+
puts_title "Request sent"
|
|
176
|
+
puts "Website #{q site} scheduled for deletion."
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def name_of_current
|
|
180
|
+
ENV['SITEID'] || clean_name(Pathname.pwd.basename)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def fetch_current
|
|
184
|
+
Website[name_of_current]
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def fetch_current!
|
|
188
|
+
fetch_current or
|
|
189
|
+
error! <<-MSG
|
|
190
|
+
The current website is undeclared yet (or at least not as
|
|
191
|
+
#{q name_of_current}). Run #{qcommand "website:declare"} to declare it.
|
|
192
|
+
MSG
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def autodetect_app_type
|
|
196
|
+
types = AppType.all.to_a
|
|
197
|
+
static = types.find { |t| t.short == 'static' }
|
|
198
|
+
(types - [static]).
|
|
199
|
+
sort_by { |t| %w(rails php).index(t.short) || -1 }.
|
|
200
|
+
each { |apptype|
|
|
201
|
+
if test = apptype.detection
|
|
202
|
+
filetype, path = test.split(' ', 2)
|
|
203
|
+
return apptype if Kernel.test(filetype, path)
|
|
204
|
+
end
|
|
205
|
+
}
|
|
206
|
+
static
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def show(site, *args)
|
|
210
|
+
list_displayer(*args).display_single_entry(site)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def list_displayer(include_status=false)
|
|
214
|
+
Utilities::ListDisplayer.new(:title => :name) do |t|
|
|
215
|
+
t.col("Status") { "Declared" } if include_status
|
|
216
|
+
t.col("Name", :name)
|
|
217
|
+
t.col("Type", :app_type)
|
|
218
|
+
t.col("Domains") { |s| (domains = s.domains.to_a).any? ? domains * ', ' : '(none)' }
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Flucti
|
|
2
|
+
module Utilities
|
|
3
|
+
SUPPORT_EMAIL_ADDR = "support@flucti.com"
|
|
4
|
+
|
|
5
|
+
autoload :CoreExt, 'flucti/utilities/core_ext'
|
|
6
|
+
autoload :UserInterface, 'flucti/utilities/user_interface'
|
|
7
|
+
autoload :TaskPacking, 'flucti/utilities/task_packing'
|
|
8
|
+
autoload :Miscellaneous, 'flucti/utilities/miscellaneous'
|
|
9
|
+
autoload :Table, 'flucti/utilities/table'
|
|
10
|
+
autoload :ListDisplayer, 'flucti/utilities/list_displayer'
|
|
11
|
+
autoload :ProgressBar, 'flucti/utilities/progress_bar'
|
|
12
|
+
autoload :ConnectionErrorHandling, 'flucti/utilities/connection_error_handling'
|
|
13
|
+
|
|
14
|
+
include UserInterface
|
|
15
|
+
include TaskPacking
|
|
16
|
+
include Miscellaneous
|
|
17
|
+
|
|
18
|
+
extend self
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Flucti
|
|
2
|
+
module Utilities
|
|
3
|
+
module ConnectionErrorHandling
|
|
4
|
+
def self.included(target)
|
|
5
|
+
target.module_eval do
|
|
6
|
+
alias_method_chain :request, 'exception_handling'
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def request_with_exception_handling(*args, &block)
|
|
11
|
+
request_without_exception_handling(*args, &block)
|
|
12
|
+
rescue => e
|
|
13
|
+
Handler.handle(e) or raise e
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module Handler
|
|
17
|
+
extend self, Utilities
|
|
18
|
+
|
|
19
|
+
def handle(err)
|
|
20
|
+
case err
|
|
21
|
+
when WebService::BadGateway
|
|
22
|
+
error! <<-MSG
|
|
23
|
+
The VPS you attempted to perform an action on returned an error.
|
|
24
|
+
It may be out of memory or disk space. Try running
|
|
25
|
+
#{qcommand 'vps:run CMD="vmstat -s -S M"'} and
|
|
26
|
+
#{qcommand 'vps:run CMD="df -h"'} respectively to determine
|
|
27
|
+
whether it's the case or not.
|
|
28
|
+
MSG
|
|
29
|
+
when WebService::ServiceUnavailable, WebService::TimeoutError, Errno::ECONNREFUSED
|
|
30
|
+
error! <<-MSG
|
|
31
|
+
It looks like we are currently performing maintenance on our
|
|
32
|
+
servers. Please retry later.
|
|
33
|
+
MSG
|
|
34
|
+
when WebService::GatewayTimeout
|
|
35
|
+
error! <<-MSG
|
|
36
|
+
The VPS you attempted to perform an action on did not respond in
|
|
37
|
+
time. Please check its system load averages and retry.
|
|
38
|
+
MSG
|
|
39
|
+
when WebService::ServerError
|
|
40
|
+
error! <<-MSG
|
|
41
|
+
An error occurred while processing your request. We have be
|
|
42
|
+
notified about this error and will work on fixing it. We
|
|
43
|
+
apologize for the inconvenience. Please retry later.
|
|
44
|
+
MSG
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Flucti
|
|
2
|
+
module Utilities
|
|
3
|
+
module CoreExt
|
|
4
|
+
def self.apply!
|
|
5
|
+
# Proper version of #constantize, since ActiveSupport's behaves strangely.
|
|
6
|
+
String.class_eval do
|
|
7
|
+
def constantize
|
|
8
|
+
split('::').inject(Object) { |mod, name| mod.const_get(name) }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
Pathname.class_eval do
|
|
13
|
+
alias_method :/, :+
|
|
14
|
+
protected :+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Thorough version of `unhook!'.
|
|
18
|
+
ActiveSupport::Dependencies.unhook!
|
|
19
|
+
ActiveSupport::Dependencies::ClassConstMissing.module_eval do
|
|
20
|
+
def const_missing(*args)
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
ActiveSupport::Inflector.inflections do |inflect|
|
|
26
|
+
inflect.singular('databases', 'database')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
WebService::RemoteCollection.class_eval do
|
|
30
|
+
include ConnectionErrorHandling
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|