kibo 0.1.2 → 0.3.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/Gemfile +2 -1
- data/Gemfile.lock +46 -0
- data/kibo.gemspec +2 -2
- data/lib/kibo/bin/yuicompressor-2.4.7.jar +0 -0
- data/lib/kibo/commandline.rb +46 -55
- data/lib/kibo/commands/compress.rb +85 -0
- data/lib/kibo/commands/create.rb +56 -0
- data/lib/kibo/commands/deploy.rb +69 -0
- data/lib/kibo/commands/generate.rb +53 -0
- data/lib/kibo/commands/info.rb +19 -0
- data/lib/kibo/commands/reconfigure.rb +12 -0
- data/lib/kibo/commands/spin.rb +39 -0
- data/lib/kibo/commands.rb +44 -0
- data/lib/kibo/config.rb +22 -10
- data/lib/kibo/helpers/heroku.rb +75 -0
- data/lib/kibo/helpers/info.rb +50 -0
- data/lib/kibo/helpers.rb +70 -0
- data/lib/kibo/log.rb +29 -3
- data/lib/kibo/system.rb +32 -12
- data/lib/kibo/version.rb +1 -1
- data/lib/kibo.rb +10 -196
- data/man/kibo.1 +65 -12
- data/man/kibo.1.html +63 -19
- data/man/kibo.1.markdown +57 -17
- data/man/kibo.1.ronn +55 -17
- metadata +34 -5
@@ -0,0 +1,75 @@
|
|
1
|
+
# It would be great if we could just use Heroku.read_credentials or `heroku whoami`
|
2
|
+
# to check for a user's current login. Well, we can't:
|
3
|
+
#
|
4
|
+
# - since heroku aggressively pushes its heroku toolbelt people
|
5
|
+
# might be forced to uninstall the heroku gem.
|
6
|
+
# - `heroku whoami` blocks for input, if the user is not logged in.
|
7
|
+
#
|
8
|
+
# Hence this code, which is based on code from the heroku gem.
|
9
|
+
#
|
10
|
+
# == Copyright and licensing ==================================================
|
11
|
+
#
|
12
|
+
# The heroku gem is licensed under the terms of the MIT license,
|
13
|
+
# see the file License.MIT.
|
14
|
+
#
|
15
|
+
# The heroku has been created by Adam Wiggins, and is currently maintained
|
16
|
+
# by Wesley Beary.
|
17
|
+
module Kibo::Helpers::Heroku
|
18
|
+
require "netrc"
|
19
|
+
|
20
|
+
def whoami
|
21
|
+
(read_credentials || []).first
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def host
|
27
|
+
ENV['HEROKU_HOST'] || default_host
|
28
|
+
end
|
29
|
+
|
30
|
+
def default_host
|
31
|
+
"heroku.com"
|
32
|
+
end
|
33
|
+
|
34
|
+
def netrc_path
|
35
|
+
default = Netrc.default_path
|
36
|
+
encrypted = default + ".gpg"
|
37
|
+
if File.exists?(encrypted)
|
38
|
+
encrypted
|
39
|
+
else
|
40
|
+
default
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def netrc # :nodoc:
|
45
|
+
@netrc ||= begin
|
46
|
+
File.exists?(netrc_path) && Netrc.read(netrc_path)
|
47
|
+
rescue => error
|
48
|
+
if error.message =~ /^Permission bits for/
|
49
|
+
perm = File.stat(netrc_path).mode & 0777
|
50
|
+
abort("Permissions #{perm} for '#{netrc_path}' are too open. You should run `chmod 0600 #{netrc_path}` so that your credentials are NOT accessible by others.")
|
51
|
+
else
|
52
|
+
raise error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_credentials
|
58
|
+
if ENV['HEROKU_API_KEY']
|
59
|
+
['', ENV['HEROKU_API_KEY']]
|
60
|
+
else
|
61
|
+
# read netrc credentials if they exist
|
62
|
+
if netrc
|
63
|
+
# force migration of long api tokens (80 chars) to short ones (40)
|
64
|
+
# #write_credentials rewrites both api.* and code.*
|
65
|
+
credentials = netrc["api.#{host}"]
|
66
|
+
if credentials && credentials[1].length > 40
|
67
|
+
@credentials = [ credentials[0], credentials[1][0,40] ]
|
68
|
+
write_credentials
|
69
|
+
end
|
70
|
+
|
71
|
+
netrc["api.#{host}"]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Kibo::Helpers::Info < Array
|
2
|
+
def self.print(out = STDOUT, &block)
|
3
|
+
out.puts build(&block).to_s
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.build(&block)
|
7
|
+
info = new
|
8
|
+
yield info
|
9
|
+
info
|
10
|
+
end
|
11
|
+
|
12
|
+
def head(msg)
|
13
|
+
push [ :head, msg ]
|
14
|
+
end
|
15
|
+
|
16
|
+
def line(msg, value)
|
17
|
+
push [ :line, msg, value ]
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
key_length = map do |kind, msg, value|
|
22
|
+
kind == :line ? msg.length : 0
|
23
|
+
end.max
|
24
|
+
|
25
|
+
key_length = 60 if key_length > 60
|
26
|
+
|
27
|
+
key_format = "%#{key_length + 4}s"
|
28
|
+
|
29
|
+
map do |kind, msg, value|
|
30
|
+
case kind
|
31
|
+
when :head
|
32
|
+
"== #{msg} " + "=" * (100 - msg.length)
|
33
|
+
when :line
|
34
|
+
case value
|
35
|
+
when [], nil then value = "<none>"
|
36
|
+
when Array then value = value.map(&:inspect).join(", ")
|
37
|
+
end
|
38
|
+
|
39
|
+
if msg == ""
|
40
|
+
"#{key_format % msg} #{value}"
|
41
|
+
elsif msg.length > key_length
|
42
|
+
msg = msg[0..20] + "..." + msg[(25 - key_length) ..-1]
|
43
|
+
"#{key_format % msg}: #{value}"
|
44
|
+
else
|
45
|
+
"#{key_format % msg}: #{value}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end.join("\n")
|
49
|
+
end
|
50
|
+
end
|
data/lib/kibo/helpers.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Kibo::Helpers
|
2
|
+
end
|
3
|
+
|
4
|
+
require_relative "./helpers/heroku"
|
5
|
+
require_relative "./helpers/info"
|
6
|
+
|
7
|
+
module Kibo::Helpers
|
8
|
+
extend self
|
9
|
+
|
10
|
+
extend Heroku
|
11
|
+
|
12
|
+
def check_missing_remotes(mode = :warn)
|
13
|
+
return if missing_remotes.empty?
|
14
|
+
|
15
|
+
if mode == :warn
|
16
|
+
W "Ignoring missing remote(s)", *missing_remotes
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
E <<-MSG
|
21
|
+
Missing remote(s): #{missing_remotes.map(&:inspect).join(", ")}. Run
|
22
|
+
|
23
|
+
kibo --environment #{environment} create --all # ... to create all missing remotes.
|
24
|
+
kibo --environment #{environment} spinup --force # ... to ignore missing remotes.
|
25
|
+
|
26
|
+
MSG
|
27
|
+
end
|
28
|
+
|
29
|
+
# -- configure remotes ----------------------------------------------
|
30
|
+
|
31
|
+
def configure_remote!(remote)
|
32
|
+
heroku "config:set",
|
33
|
+
"RACK_ENV=#{environment}",
|
34
|
+
"RAILS_ENV=#{environment}",
|
35
|
+
"INSTANCE=#{instance_for_remote(remote)}",
|
36
|
+
"--app", remote
|
37
|
+
end
|
38
|
+
|
39
|
+
def instance_for_remote(remote)
|
40
|
+
remote[config.namespace.length + 1 .. -1]
|
41
|
+
end
|
42
|
+
|
43
|
+
def configure_remote(remote)
|
44
|
+
# the correct value for the INSTANCE configuration setting is the
|
45
|
+
# name of the of the remote without the namespace part; e.g. the
|
46
|
+
# INSTANCE for the remote named "bountyhill-staging-twirl2" is
|
47
|
+
# "staging-twirl2".
|
48
|
+
instance = remote[config.namespace.length + 1 .. -1]
|
49
|
+
current_instance = heroku "config:get", "INSTANCE", "--app", remote
|
50
|
+
return if instance == current_instance
|
51
|
+
end
|
52
|
+
|
53
|
+
# -- which remotes are defined, present and configured --------------
|
54
|
+
|
55
|
+
def expected_remotes
|
56
|
+
namespace, environment = Kibo.config.namespace, Kibo.environment
|
57
|
+
|
58
|
+
Kibo.config.processes.map do |name, count|
|
59
|
+
1.upto(count).map { |idx| "#{namespace}-#{environment}-#{name}#{idx}" }
|
60
|
+
end.flatten.sort
|
61
|
+
end
|
62
|
+
|
63
|
+
def configured_remotes
|
64
|
+
Kibo.config.remotes_by_process.values.flatten
|
65
|
+
end
|
66
|
+
|
67
|
+
def missing_remotes
|
68
|
+
expected_remotes - configured_remotes
|
69
|
+
end
|
70
|
+
end
|
data/lib/kibo/log.rb
CHANGED
@@ -1,18 +1,44 @@
|
|
1
|
+
require "bundler/ui"
|
2
|
+
require "thor/shell"
|
3
|
+
|
4
|
+
UI = Bundler::UI::Shell.new(Thor::Shell::Color.new)
|
5
|
+
|
1
6
|
def log_message(msg, *args)
|
2
7
|
return msg if args.empty?
|
3
8
|
"#{msg}: " + args.map(&:inspect).join(", ")
|
4
9
|
end
|
5
10
|
|
6
11
|
def D(*args)
|
7
|
-
|
12
|
+
UI.info log_message(*args)
|
8
13
|
end
|
9
14
|
|
10
15
|
def W(*args)
|
11
|
-
|
16
|
+
UI.warn log_message(*args)
|
12
17
|
end
|
13
18
|
|
14
19
|
def E(*args)
|
15
|
-
|
20
|
+
UI.error log_message(*args)
|
16
21
|
exit 1
|
17
22
|
end
|
18
23
|
|
24
|
+
def B(*args, &block)
|
25
|
+
msg = log_message(*args)
|
26
|
+
W msg
|
27
|
+
|
28
|
+
start = Time.now
|
29
|
+
yield.tap do
|
30
|
+
W "#{msg}: #{(1000 * (Time.now - start)).to_i} msecs."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Success!
|
35
|
+
def S(*args)
|
36
|
+
UI.confirm log_message(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
def confirm!(msg)
|
40
|
+
puts msg
|
41
|
+
puts "\n\nPress ^C to abort or return to continue."
|
42
|
+
|
43
|
+
STDIN.readline
|
44
|
+
end
|
data/lib/kibo/system.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Kibo::System
|
2
2
|
extend self
|
3
|
-
|
3
|
+
|
4
4
|
def heroku(*args)
|
5
5
|
sys! "heroku", *args
|
6
6
|
end
|
@@ -10,22 +10,42 @@ module Kibo::System
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def sys(*args)
|
13
|
+
cmd = build_command(*args)
|
14
|
+
result = Kernel.send "`", "bash -c \"#{cmd}\""
|
15
|
+
if command_succeeded?(cmd)
|
16
|
+
result.chomp
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def sys!(*args)
|
21
|
+
sys(*args) || exit(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
def sh(*args)
|
25
|
+
cmd = build_command(*args)
|
26
|
+
system(cmd)
|
27
|
+
command_succeeded?(cmd)
|
28
|
+
end
|
29
|
+
|
30
|
+
def sh!(*args)
|
31
|
+
sh(*args) || exit(1)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def build_command(*args)
|
13
37
|
quiet = args.pop if args.last == :quiet
|
38
|
+
args[0].sub!(/^kibo\b/, $0)
|
14
39
|
cmd = args.map(&:to_s).join(" ")
|
15
40
|
W cmd unless quiet
|
16
|
-
|
17
|
-
# A command is run because it either is "quiet", i.e. is non-obstrusive anyway,
|
18
|
-
# or we are not in a dry. Dry run mode could go with some improvements, though.
|
19
|
-
if quiet || !Kibo::CommandLine.dry?
|
20
|
-
stdout = Kernel.send "`", "bash -c \"#{cmd}\""
|
21
|
-
stdout.chomp if $?.exitstatus == 0
|
22
|
-
else
|
23
|
-
""
|
24
|
-
end
|
41
|
+
cmd
|
25
42
|
end
|
26
43
|
|
27
|
-
def
|
28
|
-
|
44
|
+
def command_succeeded?(cmd)
|
45
|
+
return true if $?.exitstatus == 0
|
46
|
+
|
47
|
+
UI.error("Command failed: #{cmd}")
|
48
|
+
false
|
29
49
|
end
|
30
50
|
end
|
31
51
|
|
data/lib/kibo/version.rb
CHANGED
data/lib/kibo.rb
CHANGED
@@ -7,215 +7,29 @@ end
|
|
7
7
|
require_relative "kibo/log"
|
8
8
|
require_relative "kibo/system"
|
9
9
|
require_relative "kibo/config"
|
10
|
+
require_relative "kibo/commands"
|
10
11
|
require_relative "kibo/commandline"
|
11
12
|
|
12
13
|
module Kibo
|
13
14
|
extend self
|
14
|
-
|
15
|
+
|
15
16
|
def config
|
16
|
-
@config ||= Config.new(
|
17
|
+
@config ||= Config.new(kibofile)
|
17
18
|
end
|
18
19
|
|
19
20
|
def environment
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def expected_remotes
|
24
|
-
config.processes.inject([]) do |ary, (name, count)|
|
25
|
-
ary.concat 1.upto(count).map { |idx| "#{config.namespace}-#{environment}-#{name}#{idx}" }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def configured_remotes
|
30
|
-
config.remotes_by_process.values.flatten
|
31
|
-
end
|
32
|
-
|
33
|
-
def missing_remotes
|
34
|
-
expected_remotes - configured_remotes
|
35
|
-
end
|
36
|
-
|
37
|
-
# -- configure a remote
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def instance_for_remote(remote)
|
42
|
-
remote[config.namespace.length + 1 .. -1]
|
43
|
-
end
|
44
|
-
|
45
|
-
public
|
46
|
-
|
47
|
-
def configure_remote!(remote)
|
48
|
-
heroku "config:set",
|
49
|
-
"RACK_ENV=#{environment}",
|
50
|
-
"RAILS_ENV=#{environment}",
|
51
|
-
"INSTANCE=#{instance_for_remote(remote)}",
|
52
|
-
"--app", remote
|
53
|
-
end
|
54
|
-
|
55
|
-
def configure_remote(remote)
|
56
|
-
# the correct value for the INSTANCE configuration setting is the
|
57
|
-
# name of the of the remote without the namespace part; e.g. the
|
58
|
-
# INSTANCE for the remote named "bountyhill-staging-twirl2" is
|
59
|
-
# "staging-twirl2".
|
60
|
-
instance = remote[config.namespace.length + 1 .. -1]
|
61
|
-
current_instance = heroku "config:get", "INSTANCE", "--app", remote
|
62
|
-
return if instance == current_instance
|
63
|
-
end
|
64
|
-
|
65
|
-
# --spin up/spin down remotes
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def spin(processes)
|
70
|
-
config.remotes_by_process.each do |name, remotes|
|
71
|
-
number_of_processes = processes[name] || 0
|
72
|
-
|
73
|
-
remotes.each do |remote|
|
74
|
-
if number_of_processes > 0
|
75
|
-
configure_remote remote
|
76
|
-
heroku "ps:scale", "#{name}=1", "--app", remote
|
77
|
-
number_of_processes -= 1
|
78
|
-
else
|
79
|
-
heroku "ps:scale", "#{name}=0", "--app", remote
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
if number_of_processes > 0
|
84
|
-
W "Missing #{name} remote(s)", number_of_processes
|
85
|
-
end
|
86
|
-
end
|
21
|
+
CommandLine.environment
|
87
22
|
end
|
88
23
|
|
89
|
-
|
90
|
-
|
91
|
-
def spinup
|
92
|
-
check_missing_remotes(CommandLine.force? ? :warn : :error)
|
93
|
-
spin config.processes
|
94
|
-
end
|
95
|
-
|
96
|
-
def spindown
|
97
|
-
spin({})
|
98
|
-
end
|
99
|
-
|
100
|
-
# reconfigure existing remotes
|
101
|
-
public
|
102
|
-
|
103
|
-
# kibo [options] reconfigure ... reconfigure all existing remotes
|
104
|
-
def reconfigure
|
105
|
-
check_missing_remotes :warn
|
106
|
-
|
107
|
-
configured_remotes.each do |remote|
|
108
|
-
configure_remote! remote
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def prepare_deployment
|
115
|
-
end
|
116
|
-
|
117
|
-
def deploy_remote!(remote)
|
118
|
-
git "push", remote, "master"
|
119
|
-
end
|
120
|
-
|
121
|
-
public
|
122
|
-
|
123
|
-
def deploy
|
124
|
-
check_missing_remotes(CommandLine.force? ? :warn : :error)
|
125
|
-
|
126
|
-
prepare_deployment
|
127
|
-
configured_remotes.each do |remote|
|
128
|
-
deploy_remote! remote
|
129
|
-
end
|
130
|
-
|
131
|
-
W "Deployment succeeded."
|
24
|
+
def run
|
25
|
+
Commands.send CommandLine.subcommand
|
132
26
|
end
|
133
|
-
|
134
|
-
private
|
135
|
-
|
136
|
-
def check_missing_remotes(mode = :warn)
|
137
|
-
return if missing_remotes.empty?
|
138
|
-
|
139
|
-
if mode == :warn
|
140
|
-
W "Ignoring missing remote(s)", *missing_remotes
|
141
|
-
return
|
142
|
-
end
|
143
|
-
|
144
|
-
E <<-MSG
|
145
|
-
Missing remote(s): #{missing_remotes.map(&:inspect).join(", ")}. Run
|
146
27
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
MSG
|
28
|
+
def command_line
|
29
|
+
CommandLine
|
151
30
|
end
|
152
|
-
|
153
|
-
public
|
154
|
-
|
155
|
-
def create
|
156
|
-
verify_heroku_login
|
157
|
-
|
158
|
-
if CommandLine.all?
|
159
|
-
instances = missing_remotes
|
160
|
-
if instances.empty?
|
161
|
-
W "Nothing to do."
|
162
|
-
exit 0
|
163
|
-
end
|
164
|
-
else
|
165
|
-
instances = CommandLine.args
|
166
|
-
if instances.empty?
|
167
|
-
W "Add the names of the remotes to create on the command line or use the --all parameter."
|
168
|
-
exit 0
|
169
|
-
end
|
170
31
|
|
171
|
-
|
172
|
-
|
173
|
-
unless extra_instances.empty?
|
174
|
-
E <<-MSG
|
175
|
-
kibo cannot create these instances for you: #{extra_instances.map(&:inspect).join(", ")}, because I don't not know anything about these.
|
176
|
-
MSG
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
confirm! <<-MSG
|
181
|
-
I am going to create these instances: #{instances.map(&:inspect).join(", ")}. Is this what you want? Note:
|
182
|
-
You are logged in at heroku as #{config.heroku}.
|
183
|
-
MSG
|
184
|
-
|
185
|
-
instances.each do |instance|
|
186
|
-
create_instance(instance)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def confirm!(msg)
|
191
|
-
puts msg
|
192
|
-
puts "\n\nPress ^C to abort or return to continue."
|
193
|
-
|
194
|
-
STDIN.read
|
195
|
-
end
|
196
|
-
|
197
|
-
private
|
198
|
-
|
199
|
-
def verify_heroku_login
|
200
|
-
(Heroku::Auth.read_credentials || []).first.tap do |whoami|
|
201
|
-
msg = if !whoami
|
202
|
-
"Please log into heroku as #{config.heroku.inspect}."
|
203
|
-
elsif whoami != config.heroku
|
204
|
-
"You are currently logged into heroku as #{whoami.inspect}; please log in as #{config.heroku.inspect}."
|
205
|
-
end
|
206
|
-
|
207
|
-
E "#{msg}\n\n\theroku auth:login" if msg
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
def create_instance(remote)
|
212
|
-
# TODO: Test whether these instances already exist, using `heroku apps`
|
213
|
-
heroku "apps:create", remote, "--remote", remote
|
214
|
-
end
|
215
|
-
|
216
|
-
public
|
217
|
-
|
218
|
-
def run
|
219
|
-
self.send CommandLine.subcommand
|
32
|
+
def kibofile
|
33
|
+
command_line.kibofile
|
220
34
|
end
|
221
35
|
end
|
data/man/kibo.1
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
3
|
.
|
4
|
-
.TH "KIBO" "1" "
|
4
|
+
.TH "KIBO" "1" "September 2012" "Kibo 0.3.0" "Kibo Manual"
|
5
5
|
.
|
6
6
|
.SH "NAME"
|
7
7
|
\fBkibo\fR \- manage heroku applications
|
@@ -21,41 +21,94 @@
|
|
21
21
|
.br
|
22
22
|
\fBkibo [options] reconfigure\fR
|
23
23
|
.
|
24
|
+
.br
|
25
|
+
\fBkibo [options] generate\fR
|
26
|
+
.
|
24
27
|
.SH "DESCRIPTION"
|
25
|
-
kibo
|
28
|
+
kibo manages multiple application roles on single heroku dynos\.
|
26
29
|
.
|
27
30
|
.SH "DESCRIPTION"
|
28
|
-
|
31
|
+
Kibo is a perfect addition to Procfile based deployment on heroku\.com\. While heroku itself provides adequate tools to manage a single application on multiple dynos, Kibo adds tools to manage multiple application roles on single dynos with automatic instance provisioning\.
|
32
|
+
.
|
33
|
+
.P
|
34
|
+
The application roles are read from the Procfile (see foreman(1))\. The concurrency options \- i\.e\. the number of applications to run each role \- is read from the Kibofile\.
|
35
|
+
.
|
36
|
+
.SH "INSTANCE PROVISIONING"
|
37
|
+
Each instance gets automatically configured using `heroku config\. kibo sets the environment variables INSTANCE, RAILS_ENV and RACK_ENV to reflect instance role and number and runtime environment\.
|
38
|
+
.
|
39
|
+
.IP "" 4
|
40
|
+
.
|
41
|
+
.nf
|
42
|
+
|
43
|
+
INSTANCE="kibo\-staging\-web1"
|
44
|
+
RAILS_ENV="staging"
|
45
|
+
RACK_ENV="staging"
|
46
|
+
.
|
47
|
+
.fi
|
48
|
+
.
|
49
|
+
.IP "" 0
|
29
50
|
.
|
30
51
|
.SH "GLOBAL OPTIONS"
|
31
52
|
The following options control how kibo is run:
|
32
53
|
.
|
33
54
|
.TP
|
34
55
|
\fB\-e\fR, \fB\-\-environment\fR
|
35
|
-
Set the target environment\.
|
56
|
+
Set the target environment\. Defaults to "staging"
|
36
57
|
.
|
37
58
|
.TP
|
38
59
|
\fB\-k\fR, \fB\-\-kibofile\fR
|
39
|
-
Specify
|
60
|
+
Specify an alternate Kibofile to use\.
|
40
61
|
.
|
41
62
|
.TP
|
42
63
|
\fB\-p\fR, \fB\-\-procfile\fR
|
43
|
-
Specify an alternate Procfile to
|
64
|
+
Specify an alternate Procfile to use\.
|
44
65
|
.
|
45
66
|
.SH "Kibofile"
|
46
|
-
|
67
|
+
A Kibofile scaffold can be generated via \fBkibo generate\fR\. The following is an example:
|
47
68
|
.
|
48
69
|
.IP "" 4
|
49
70
|
.
|
50
71
|
.nf
|
51
72
|
|
73
|
+
kibo:
|
74
|
+
# The email of the heroku account to create app instances on heroku\.
|
75
|
+
heroku: user@domain\.com
|
76
|
+
# You instances will be called \'kiboex\-staging\-web0\', \'kiboex\-production\-worker0\', etc\.
|
77
|
+
namespace: kibo
|
52
78
|
defaults:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
twirl: 1
|
79
|
+
procfile: Procfile\.other
|
80
|
+
web: 1
|
81
|
+
worker: 1
|
57
82
|
production:
|
58
|
-
|
83
|
+
web: 1
|
84
|
+
worker: 2
|
85
|
+
.
|
86
|
+
.fi
|
87
|
+
.
|
88
|
+
.IP "" 0
|
89
|
+
.
|
90
|
+
.P
|
91
|
+
This defines the roles "web" and "worker", which are running at one resp\. two instances in the "production" environment\.
|
92
|
+
.
|
93
|
+
.SH "Example session"
|
94
|
+
This is a session using the example Kibofile from above:
|
95
|
+
.
|
96
|
+
.IP "" 4
|
97
|
+
.
|
98
|
+
.nf
|
99
|
+
|
100
|
+
# creates the heroku applications "kibo\-production\-web1",
|
101
|
+
# "kibo\-production\-worker1", and "kibo\-production\-worker2"\.
|
102
|
+
kibo \-e production create
|
103
|
+
|
104
|
+
# deploy all applications\.
|
105
|
+
kibo \-e production deploy
|
106
|
+
|
107
|
+
# start all instances
|
108
|
+
kibo \-e production spinup
|
109
|
+
|
110
|
+
# stop all instances
|
111
|
+
kibo \-e production spindown
|
59
112
|
.
|
60
113
|
.fi
|
61
114
|
.
|