capricorn 2.0.6 → 2.0.7
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/bin/capricornctl +1 -1
- data/lib/capricorn-client.rb +33 -62
- data/lib/capricorn-client/cli/applications.rb +124 -197
- data/lib/capricorn-client/cli/applications/domains.rb +61 -0
- data/lib/capricorn-client/cli/applications/gems.rb +61 -0
- data/lib/capricorn-client/cli/gems.rb +38 -16
- data/lib/capricorn-client/cli/machines.rb +17 -8
- data/lib/capricorn-client/helpers.rb +194 -48
- data/lib/capricorn/version.rb +1 -1
- metadata +30 -28
data/bin/capricornctl
CHANGED
data/lib/capricorn-client.rb
CHANGED
@@ -2,85 +2,56 @@ module Capricorn
|
|
2
2
|
require 'thor'
|
3
3
|
require 'yaml'
|
4
4
|
require 'bertrpc'
|
5
|
-
require 'highline'
|
6
5
|
require 'fileutils'
|
7
6
|
|
8
7
|
require 'capricorn-client/helpers'
|
9
8
|
|
10
|
-
|
9
|
+
class CLI < Thor
|
10
|
+
namespace "default"
|
11
|
+
|
11
12
|
require 'capricorn-client/cli/applications'
|
13
|
+
require 'capricorn-client/cli/applications/domains'
|
14
|
+
require 'capricorn-client/cli/applications/gems'
|
12
15
|
require 'capricorn-client/cli/gems'
|
13
16
|
require 'capricorn-client/cli/machines'
|
14
|
-
end
|
15
|
-
|
16
|
-
module Runner
|
17
|
-
|
18
|
-
HELP = <<-EOH
|
19
|
-
Topics:
|
20
|
-
CLUSTER applications
|
21
|
-
# manage applications
|
22
|
-
|
23
|
-
CLUSTER gems
|
24
|
-
# manage gems
|
25
|
-
|
26
|
-
CLUSTER machines
|
27
|
-
# manage machines
|
28
|
-
EOH
|
29
|
-
|
30
|
-
DEFAULT_CONFIG = <<-EOH
|
31
|
-
cluster_name:
|
32
|
-
host: localhost
|
33
|
-
port: 3457
|
34
|
-
username: dummy
|
35
|
-
password: dummy
|
36
|
-
EOH
|
37
|
-
|
38
|
-
def start
|
39
|
-
cluster_name = ARGV.shift
|
40
|
-
unless cluster_name
|
41
|
-
help
|
42
|
-
exit 1
|
43
|
-
end
|
44
17
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
exit 1
|
49
|
-
end
|
18
|
+
def self.banner(task)
|
19
|
+
"#{banner_base} #{task.formatted_usage(self, true)}"
|
20
|
+
end
|
50
21
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
Capricorn::CLI::Gems.start
|
56
|
-
when 'machines'
|
57
|
-
Capricorn::CLI::Machines.start
|
22
|
+
def help(meth=nil)
|
23
|
+
if meth && !self.respond_to?(meth)
|
24
|
+
klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
|
25
|
+
klass.start(["-h", task].compact, :shell => self.shell)
|
58
26
|
else
|
59
|
-
|
27
|
+
super
|
60
28
|
end
|
61
29
|
end
|
62
30
|
|
63
|
-
def
|
64
|
-
|
31
|
+
def method_missing(meth, *args)
|
32
|
+
meth = meth.to_s
|
33
|
+
klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
|
34
|
+
args.unshift(task) if task
|
35
|
+
klass.start(args, :shell => self.shell)
|
65
36
|
end
|
66
37
|
|
67
|
-
|
68
|
-
|
69
|
-
|
38
|
+
class_option :cluster, :type => :string, :aliases => ['-c']
|
39
|
+
class_option :machine, :type => :string, :aliases => ['-m', '-n', '--node']
|
40
|
+
class_option :application, :type => :string, :aliases => ['-a', '--app']
|
41
|
+
class_option :environment, :type => :string, :aliases => ['-e', '--env']
|
70
42
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
43
|
+
desc "deploy", "deploy an new gem"
|
44
|
+
def deploy
|
45
|
+
last = Dir.glob("pkg/*.gem").sort do |a, b|
|
46
|
+
File.stat(a).mtime <=> File.stat(b).mtime
|
47
|
+
end.last
|
48
|
+
|
49
|
+
$capr_gems_weak_push = true
|
50
|
+
|
51
|
+
invoke "gems:push", [last]
|
52
|
+
invoke "apps:fupdate"
|
82
53
|
end
|
83
54
|
|
84
|
-
extend self
|
85
55
|
end
|
56
|
+
|
86
57
|
end
|
@@ -1,256 +1,183 @@
|
|
1
|
-
class Capricorn::CLI::Applications <
|
1
|
+
class Capricorn::CLI::Applications < Capricorn::CLI
|
2
|
+
|
3
|
+
require 'public_suffix_service'
|
4
|
+
|
2
5
|
include Capricorn::Helpers
|
3
|
-
|
6
|
+
|
7
|
+
namespace :apps
|
8
|
+
|
9
|
+
desc "init", "initialize the .capricorn.yml file"
|
10
|
+
def init
|
11
|
+
if File.file?('.capricorn.yml')
|
12
|
+
halt ".capricorn.yml already exists"
|
13
|
+
end
|
14
|
+
|
15
|
+
File.open(".capricorn.yml", 'w+') do |file|
|
16
|
+
file.write <<-EOS
|
17
|
+
staging:
|
18
|
+
cluster: CLUSTER_NAME
|
19
|
+
machine: MACHINE_ID
|
20
|
+
application: APPLICATION_ID
|
21
|
+
EOS
|
22
|
+
end
|
23
|
+
info "initialized .capricorn.yml"
|
24
|
+
end
|
25
|
+
|
4
26
|
desc "list", "list all applications on MACHINE"
|
5
27
|
def list
|
6
|
-
machine = select_machine
|
7
|
-
|
8
28
|
apps = client.call.applications.all(machine.to_sym).last || []
|
9
29
|
apps.collect! do |app|
|
10
|
-
[app[
|
30
|
+
[app[3], app[1]]
|
11
31
|
end
|
12
|
-
apps.
|
13
|
-
|
14
|
-
ui.table %w( Id Name ), apps, :columns_across, 2
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "info", "get info of an application on MACHINE"
|
18
|
-
def info
|
19
|
-
machine, id = *select_application
|
20
|
-
app = find_app(machine, id)
|
21
|
-
show_app(app)
|
22
|
-
end
|
23
|
-
|
24
|
-
desc "create", "create an application on MACHINE"
|
25
|
-
def create
|
26
|
-
machine = select_machine
|
27
|
-
name = ui.ask("name: ") do |q|
|
28
|
-
q.validate = /^.+$/
|
32
|
+
apps.sort! do |a,b|
|
33
|
+
a[0] <=> b[0]
|
29
34
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
width = apps.inject(0) { |m, (n, _)| (m > n.size ? m : n.size) }
|
36
|
+
|
37
|
+
apps.each do |(name, id)|
|
38
|
+
padding = ' ' * (width - name.size)
|
39
|
+
puts "#{name}#{padding} : #{id}"
|
34
40
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "show", "get info of an application on MACHINE"
|
44
|
+
def show
|
45
|
+
puts " Id: #{application_info[1]}"
|
46
|
+
puts " Machine: #{application_info[2]}"
|
47
|
+
puts " Name: #{application_info[3]}"
|
48
|
+
puts " Environment: #{application_info[5]}"
|
49
|
+
puts " User: #{application_info[6]}"
|
50
|
+
puts " Group: #{application_info[7]}"
|
51
|
+
puts " Root: #{application_info[8]}"
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "create NAME ENVIRONMENT DOMAINS...", "create an application on MACHINE"
|
55
|
+
def create(name, environment, *domains)
|
56
|
+
name = name.to_s.strip
|
57
|
+
if name.empty?
|
58
|
+
halt "Please choose a name!"
|
59
|
+
end
|
60
|
+
|
61
|
+
environment = environment.to_s.strip
|
62
|
+
unless %w( production development staging testing ).include?(environment)
|
63
|
+
halt "Please select a valid environment!"
|
38
64
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
65
|
+
environment = environment.to_sym
|
66
|
+
|
67
|
+
domains = domains.flatten do |domain|
|
68
|
+
if domain
|
69
|
+
domain = domain.to_s.downcase.strip.sub(/^www\./, '')
|
70
|
+
begin
|
71
|
+
PublicSuffixService.parse(domain).to_s
|
72
|
+
rescue Exception
|
73
|
+
halt "invalid domain: #{domain}"
|
74
|
+
end
|
42
75
|
end
|
43
|
-
|
44
|
-
|
76
|
+
end.compact.uniq
|
77
|
+
domains.delete('')
|
78
|
+
if domains.empty?
|
79
|
+
halt "Please add at least one domain!"
|
45
80
|
end
|
46
|
-
|
47
|
-
domains = domains.flatten.compact
|
48
|
-
domains = domains.collect { |d| d.downcase.sub(/^www\./, '') }
|
49
|
-
domains = domains.uniq
|
50
|
-
|
51
|
-
environment = environment.to_sym
|
52
|
-
|
81
|
+
|
53
82
|
p client.call.applications.create(machine.to_sym, name, domains, environment)
|
54
83
|
end
|
55
|
-
|
56
|
-
desc "import", "import an application on MACHINE (only use this from an application dir)"
|
57
|
-
def import
|
84
|
+
|
85
|
+
desc "import NAME ENVIRONMENT DOMAINS...", "import an application on MACHINE (only use this from an application dir)"
|
86
|
+
def import(name, environment, *domains)
|
58
87
|
root = File.expand_path(Dir.pwd)
|
59
|
-
|
88
|
+
|
60
89
|
unless File.file?(File.join(root, "host/config/milkshake.yml"))
|
61
|
-
|
62
|
-
|
63
|
-
exit 1
|
90
|
+
info 'no milkshake config was found'
|
91
|
+
halt 'This doesn\'t appear to be a milkshake app!'
|
64
92
|
end
|
65
|
-
|
93
|
+
|
66
94
|
unless File.directory?(File.join(root, "shared"))
|
67
|
-
|
68
|
-
|
69
|
-
exit 1
|
95
|
+
info 'no shared dir was found'
|
96
|
+
halt 'This doesn\'t appear to be a milkshake app!'
|
70
97
|
end
|
71
|
-
|
98
|
+
|
72
99
|
gems = YAML.load_file(File.join(root, "host/config/milkshake.yml"))
|
73
100
|
gems = (gems['gems'].keys rescue [])
|
74
101
|
if gems.empty?
|
75
|
-
|
76
|
-
|
77
|
-
exit 1
|
102
|
+
info 'no gems were found'
|
103
|
+
halt 'This doesn\'t appear to be a milkshake app!'
|
78
104
|
end
|
79
|
-
|
105
|
+
|
80
106
|
stats = (File.stat(File.join(root, "host/config/environment.rb")) rescue nil)
|
81
107
|
unless stats
|
82
|
-
|
83
|
-
|
84
|
-
exit 1
|
108
|
+
info 'no environment.rb was found'
|
109
|
+
halt 'This doesn\'t appear to be a milkshake app!'
|
85
110
|
end
|
86
|
-
|
111
|
+
|
87
112
|
uid = (Etc.getpwuid(stats.uid).name rescue nil)
|
88
113
|
unless uid
|
89
|
-
|
90
|
-
|
91
|
-
exit 1
|
114
|
+
info 'no uid was found'
|
115
|
+
halt 'This doesn\'t appear to be a milkshake app!'
|
92
116
|
end
|
93
|
-
|
117
|
+
|
94
118
|
gid = (Etc.getgrgid(stats.gid).name rescue nil)
|
95
119
|
unless gid
|
96
|
-
|
97
|
-
|
98
|
-
exit 1
|
99
|
-
end
|
100
|
-
|
101
|
-
machine = select_machine
|
102
|
-
name = ui.ask("name: ") do |q|
|
103
|
-
q.validate = /^.+$/
|
104
|
-
end
|
105
|
-
environment = ui.choose do |q|
|
106
|
-
q.choices(*%w( production development staging testing ))
|
107
|
-
q.prompt = "environment: "
|
108
|
-
q.default = 'production'
|
120
|
+
info 'no gid was found'
|
121
|
+
halt 'This doesn\'t appear to be a milkshake app!'
|
109
122
|
end
|
110
|
-
|
111
|
-
|
112
|
-
|
123
|
+
|
124
|
+
name = name.to_s.strip
|
125
|
+
if name.empty?
|
126
|
+
halt "Please choose a name!"
|
113
127
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
break if domain.strip.empty?
|
119
|
-
domains << domain
|
128
|
+
|
129
|
+
environment = environment.to_s.strip
|
130
|
+
unless %w( production development staging testing ).include?(environment)
|
131
|
+
halt "Please select a valid environment!"
|
120
132
|
end
|
121
|
-
|
122
|
-
domains = domains.flatten.compact
|
123
|
-
domains = domains.collect { |d| d.downcase.sub(/^www\./, '') }
|
124
|
-
domains = domains.uniq
|
125
|
-
|
126
133
|
environment = environment.to_sym
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
app[4] ||= []
|
137
|
-
app[9] ||= []
|
138
|
-
app[10] ||= []
|
139
|
-
|
140
|
-
loop do
|
141
|
-
print "\e[H\e[2J" ; $stdout.flush
|
142
|
-
|
143
|
-
show_app(app)
|
144
|
-
|
145
|
-
puts
|
146
|
-
|
147
|
-
ui.choose do |q|
|
148
|
-
q.header = "Actions"
|
149
|
-
q.prompt = 'What do you wan to do? '
|
150
|
-
|
151
|
-
q.choice('gem-add') do
|
152
|
-
name = ui.ask("enter a gem name: ") do |q|
|
153
|
-
q.validate = /^([a-zA-Z0-9_-]+)?$/
|
154
|
-
end
|
155
|
-
app[10] << name unless name.strip.empty?
|
134
|
+
|
135
|
+
domains = domains.flatten do |domain|
|
136
|
+
if domain
|
137
|
+
domain = domain.to_s.downcase.strip.sub(/^www\./, '')
|
138
|
+
begin
|
139
|
+
PublicSuffixService.parse(domain).to_s
|
140
|
+
rescue Exception
|
141
|
+
halt "invalid domain: #{domain}"
|
156
142
|
end
|
157
|
-
|
158
|
-
q.choice('gem-remove') do
|
159
|
-
g = ui.choose do |q|
|
160
|
-
q.header = "Gems"
|
161
|
-
q.prompt = 'choose a gem to remove: '
|
162
|
-
q.choices(*app[10])
|
163
|
-
end
|
164
|
-
app[10].delete(g)
|
165
|
-
end
|
166
|
-
|
167
|
-
q.choice('domain-add') do
|
168
|
-
domain = ui.ask("enter a domain: ") do |q|
|
169
|
-
q.validate = /^([\w\d]+(\.[\w\d]+)*)?$/
|
170
|
-
end
|
171
|
-
app[4] << domain unless domain.strip.empty?
|
172
|
-
end
|
173
|
-
|
174
|
-
q.choice('domain-remove') do
|
175
|
-
domain = ui.choose do |q|
|
176
|
-
q.header = "Domains"
|
177
|
-
q.prompt = 'choose a domain to remove: '
|
178
|
-
q.choices(*app[4])
|
179
|
-
end
|
180
|
-
app[4].delete(domain)
|
181
|
-
end
|
182
|
-
|
183
|
-
q.choice('abort') do
|
184
|
-
exit(0)
|
185
|
-
end
|
186
|
-
|
187
|
-
q.choice('commit') do
|
188
|
-
p client.call.applications.update(machine.to_sym, id, app[4], app[10])
|
189
|
-
exit(0)
|
190
|
-
end
|
191
|
-
|
192
143
|
end
|
144
|
+
end.compact.uniq
|
145
|
+
domains.delete('')
|
146
|
+
if domains.empty?
|
147
|
+
halt "Please add at least one domain!"
|
193
148
|
end
|
149
|
+
|
150
|
+
p client.call.applications.import(machine.to_sym, name, domains, environment, root, gems, uid, gid)
|
194
151
|
end
|
195
|
-
|
152
|
+
|
196
153
|
desc "fupdate", "force update an application on MACHINE"
|
197
154
|
def fupdate
|
198
|
-
machine, id = *
|
155
|
+
machine, id = *application
|
199
156
|
p client.call.applications.fupdate(machine.to_sym, id)
|
200
157
|
end
|
201
|
-
|
158
|
+
|
202
159
|
desc "relink", "relink an application on MACHINE"
|
203
160
|
def relink
|
204
|
-
machine, id = *
|
161
|
+
machine, id = *application
|
205
162
|
p client.call.applications.relink(machine.to_sym, id)
|
206
163
|
end
|
207
|
-
|
164
|
+
|
208
165
|
desc "restart", "restart an application on MACHINE"
|
209
166
|
def restart
|
210
|
-
machine, id = *
|
167
|
+
machine, id = *application
|
211
168
|
p client.call.applications.restart(machine.to_sym, id)
|
212
169
|
end
|
213
|
-
|
170
|
+
|
214
171
|
desc "start", "start an application on MACHINE"
|
215
172
|
def start
|
216
|
-
machine, id = *
|
173
|
+
machine, id = *application
|
217
174
|
p client.call.applications.start(machine.to_sym, id)
|
218
175
|
end
|
219
|
-
|
176
|
+
|
220
177
|
desc "stop", "stop an application on MACHINE"
|
221
178
|
def stop
|
222
|
-
machine, id = *
|
179
|
+
machine, id = *application
|
223
180
|
p client.call.applications.stop(machine.to_sym, id)
|
224
181
|
end
|
225
|
-
|
226
|
-
private
|
227
|
-
|
228
|
-
def find_app(machine ,id)
|
229
|
-
apps = client.call.applications.all(machine.to_sym).last || []
|
230
|
-
app = apps.detect do |app|
|
231
|
-
app[1] == id
|
232
|
-
end
|
233
|
-
|
234
|
-
unless app
|
235
|
-
puts ui.color('Application not found!', :red)
|
236
|
-
exit(1)
|
237
|
-
end
|
238
|
-
|
239
|
-
app
|
240
|
-
end
|
241
|
-
|
242
|
-
def show_app(app)
|
243
|
-
app = app.to_a.dup
|
244
|
-
app.shift
|
245
|
-
app.pop
|
246
|
-
app.collect! do |v|
|
247
|
-
case v
|
248
|
-
when Array then v.join(', ')
|
249
|
-
else v.to_s
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
ui.table %w( Id Machine Name Domains Environment User Group Root Installed\ Gems Requested\ Gems ), app, :columns_down, 2
|
254
|
-
end
|
255
|
-
|
182
|
+
|
256
183
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Capricorn::CLI::ApplicationsDomains < Capricorn::CLI
|
2
|
+
|
3
|
+
include Capricorn::Helpers
|
4
|
+
|
5
|
+
namespace "apps:domains"
|
6
|
+
|
7
|
+
desc "list", "list all domains"
|
8
|
+
def list
|
9
|
+
application_info[4].sort! do |a, b|
|
10
|
+
a <=> b
|
11
|
+
end
|
12
|
+
application_info[4].each do |domain|
|
13
|
+
puts "- #{domain}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "add DOMAIN", "add a new domain"
|
18
|
+
def add(domain)
|
19
|
+
domain = domain.strip.sub(/^www\./, '')
|
20
|
+
|
21
|
+
begin
|
22
|
+
domain = PublicSuffixService.parse(domain).to_s
|
23
|
+
rescue Exception
|
24
|
+
halt "invalid domain: #{domain}"
|
25
|
+
end
|
26
|
+
|
27
|
+
machine, id = *application
|
28
|
+
app = application_info
|
29
|
+
|
30
|
+
if app[4].include?(domain)
|
31
|
+
halt "Domain is already configured"
|
32
|
+
end
|
33
|
+
|
34
|
+
app[4].push(domain)
|
35
|
+
|
36
|
+
p client.call.applications.update(machine.to_sym, id, app[4], app[10])
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "remove DOMAIN", "remove a domain"
|
40
|
+
def remove(domain)
|
41
|
+
domain = domain.strip.sub(/^www\./, '')
|
42
|
+
|
43
|
+
begin
|
44
|
+
domain = PublicSuffixService.parse(domain).to_s
|
45
|
+
rescue Exception
|
46
|
+
halt "invalid domain: #{domain}"
|
47
|
+
end
|
48
|
+
|
49
|
+
machine, id = *application
|
50
|
+
app = application_info
|
51
|
+
|
52
|
+
unless app[4].include?(domain)
|
53
|
+
halt "Domain is not configured"
|
54
|
+
end
|
55
|
+
|
56
|
+
app[4].delete(domain)
|
57
|
+
|
58
|
+
p client.call.applications.update(machine.to_sym, id, app[4], app[10])
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Capricorn::CLI::ApplicationsGems < Capricorn::CLI
|
2
|
+
|
3
|
+
include Capricorn::Helpers
|
4
|
+
|
5
|
+
namespace "apps:gems"
|
6
|
+
|
7
|
+
desc "list", "list all gems"
|
8
|
+
def list
|
9
|
+
application_info[9].sort! do |a,b|
|
10
|
+
a[1] <=> b[1]
|
11
|
+
end
|
12
|
+
|
13
|
+
application_info[10].sort! do |a,b|
|
14
|
+
a <=> b
|
15
|
+
end
|
16
|
+
|
17
|
+
puts "Configured gems:"
|
18
|
+
application_info[10].each do |name|
|
19
|
+
puts "- #{name}"
|
20
|
+
end
|
21
|
+
puts
|
22
|
+
|
23
|
+
puts "Used gems:"
|
24
|
+
application_info[9].each do |gem|
|
25
|
+
puts "- #{gem[1]} (#{gem[2].flatten.join('.')})"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "add GEM_NAME", "add a new gem"
|
30
|
+
def add(gem_name)
|
31
|
+
gem_name = gem_name.strip
|
32
|
+
|
33
|
+
machine, id = *application
|
34
|
+
app = application_info
|
35
|
+
|
36
|
+
if app[10].include?(gem_name)
|
37
|
+
halt "Gem is already configured"
|
38
|
+
end
|
39
|
+
|
40
|
+
app[10].push(gem_name)
|
41
|
+
|
42
|
+
p client.call.applications.update(machine.to_sym, id, app[4], app[10])
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "remove GEM_NAME", "remove a gem"
|
46
|
+
def remove(gem_name)
|
47
|
+
gem_name = gem_name.strip
|
48
|
+
|
49
|
+
machine, id = *application
|
50
|
+
app = application_info
|
51
|
+
|
52
|
+
unless app[10].include?(gem_name)
|
53
|
+
halt "Gem is not configured"
|
54
|
+
end
|
55
|
+
|
56
|
+
app[10].delete(gem_name)
|
57
|
+
|
58
|
+
p client.call.applications.update(machine.to_sym, id, app[4], app[10])
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -1,45 +1,67 @@
|
|
1
|
-
class Capricorn::CLI::Gems <
|
1
|
+
class Capricorn::CLI::Gems < Capricorn::CLI
|
2
2
|
include Capricorn::Helpers
|
3
|
-
|
3
|
+
|
4
|
+
namespace :gems
|
5
|
+
|
4
6
|
desc "push PATHS...", "push gems to capricorn"
|
5
7
|
def push(*paths)
|
6
8
|
paths = paths.flatten.collect do |path|
|
7
9
|
Dir.glob(path)
|
8
10
|
end.flatten
|
11
|
+
|
9
12
|
paths.each do |path|
|
10
13
|
begin
|
11
14
|
client.call(:stream => path).gems.push
|
12
|
-
|
15
|
+
info "Pushed: #{File.basename(path)}"
|
13
16
|
rescue BERTRPC::UserError => e
|
14
|
-
|
17
|
+
halt(e.message, $capr_gems_weak_push)
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
18
|
-
|
21
|
+
|
19
22
|
desc "missing", "list missing gems"
|
20
23
|
def missing
|
21
|
-
|
24
|
+
all = clean_missing(client.call.gems.missing)
|
25
|
+
all.sort! { |a, b| a[0] <=> b[0] }
|
26
|
+
width = all.inject(0) { |m, (name, _)| (m > name.size ? m : name.size) }
|
27
|
+
all.each do |(name, versions)|
|
28
|
+
padding = ' ' * (width - name.size)
|
29
|
+
puts "#{padding}#{name}: #{versions}"
|
30
|
+
end
|
22
31
|
end
|
23
|
-
|
32
|
+
|
24
33
|
desc "all", "list all gems"
|
25
34
|
def all
|
26
|
-
|
35
|
+
all = clean_all(client.call.gems.all)
|
36
|
+
all.sort! { |a, b| a[0] <=> b[0] }
|
37
|
+
width = all.inject(0) { |m, (name, _)| (m > name.size ? m : name.size) }
|
38
|
+
all.each do |(name, versions)|
|
39
|
+
padding = ' ' * (width - name.size)
|
40
|
+
puts "#{padding}#{name}: #{versions}"
|
41
|
+
end
|
27
42
|
end
|
28
|
-
|
43
|
+
|
29
44
|
private
|
30
|
-
|
45
|
+
|
31
46
|
def clean_all(gems)
|
32
47
|
gems = gems.last
|
33
48
|
gems.inject(Hash.new { |h,k| h[k] = [] }) do |m, g|
|
34
49
|
header, name, version = *(g.to_ary)
|
50
|
+
next(m) unless version.last
|
35
51
|
version = version.last.join('.')
|
36
52
|
m[name.to_s] << version
|
37
53
|
m
|
38
54
|
end.collect do |name, versions|
|
39
|
-
|
40
|
-
|
55
|
+
versions = versions.reverse
|
56
|
+
if versions.size > 5
|
57
|
+
versions = versions[0, 5].join(', ') + ", (and #{versions.size - 5} more)"
|
58
|
+
else
|
59
|
+
versions = versions.join(', ')
|
60
|
+
end
|
61
|
+
[name, versions]
|
62
|
+
end
|
41
63
|
end
|
42
|
-
|
64
|
+
|
43
65
|
def clean_missing(deps)
|
44
66
|
deps = deps.last if deps and deps.first == :ok
|
45
67
|
return [] if deps.nil? or deps.empty?
|
@@ -49,9 +71,9 @@ private
|
|
49
71
|
op = req.shift
|
50
72
|
version = req.shift.to_a.last.join('.')
|
51
73
|
"#{op} #{version}"
|
52
|
-
end.join(', ')
|
74
|
+
end.reverse.join(', ')
|
53
75
|
[dep.first, reqs]
|
54
|
-
end
|
76
|
+
end
|
55
77
|
end
|
56
|
-
|
78
|
+
|
57
79
|
end
|
@@ -1,20 +1,29 @@
|
|
1
|
-
class Capricorn::CLI::Machines <
|
1
|
+
class Capricorn::CLI::Machines < Capricorn::CLI
|
2
2
|
include Capricorn::Helpers
|
3
3
|
|
4
|
+
namespace :machines
|
5
|
+
|
4
6
|
desc "list", "list all machines"
|
5
7
|
def list
|
6
|
-
|
8
|
+
machines.sort! do |a, b|
|
9
|
+
a <=> b
|
10
|
+
end
|
11
|
+
|
12
|
+
puts "Machines:"
|
13
|
+
machines.each do |machine|
|
14
|
+
puts "- #{machine}"
|
15
|
+
end
|
7
16
|
end
|
8
17
|
|
9
|
-
desc "reboot
|
10
|
-
|
11
|
-
|
18
|
+
desc "reboot", "reboot a node"
|
19
|
+
method_option :node, :type => :string
|
20
|
+
def reboot
|
12
21
|
puts client.call.runtime.reboot(node.to_sym)
|
13
22
|
end
|
14
23
|
|
15
|
-
desc "selfupdate
|
16
|
-
|
17
|
-
|
24
|
+
desc "selfupdate", "update a node"
|
25
|
+
method_option :node, :type => :string
|
26
|
+
def selfupdate
|
18
27
|
puts client.call.runtime.selfupdate(node.to_sym)
|
19
28
|
end
|
20
29
|
|
@@ -1,43 +1,28 @@
|
|
1
1
|
module Capricorn::Helpers
|
2
2
|
|
3
|
-
|
4
|
-
if self.machines.size > 1
|
5
|
-
ui.choose(*self.machines)
|
6
|
-
elsif self.machines.size == 1 and ui.agree("Use machine #{self.machines.first}? ")
|
7
|
-
self.machines.first
|
8
|
-
else
|
9
|
-
puts ui.color('No machines found!!!', :red)
|
10
|
-
exit(1)
|
11
|
-
end
|
12
|
-
end
|
3
|
+
require 'abbrev'
|
13
4
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
5
|
+
DEFAULT_CONFIG = <<-EOH
|
6
|
+
cluster_name:
|
7
|
+
host: localhost
|
8
|
+
port: 3457
|
9
|
+
username: dummy
|
10
|
+
password: dummy
|
11
|
+
EOH
|
12
|
+
|
13
|
+
def application_ids
|
14
|
+
@application_ids ||= begin
|
15
|
+
apps = applications.collect do |app|
|
16
|
+
app[1]
|
17
|
+
end
|
18
|
+
apps.flatten!
|
19
|
+
apps
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
apps = client.call.applications.all(machine.to_sym).last || []
|
29
|
-
apps.collect! do |app|
|
30
|
-
app[1]
|
31
|
-
end
|
32
|
-
apps.flatten!
|
33
|
-
|
34
|
-
if apps.size > 1
|
35
|
-
[machine, ui.choose(*apps)]
|
36
|
-
elsif apps.size == 1 and ui.agree("Use application #{apps.first}? ")
|
37
|
-
[machine, apps.first]
|
38
|
-
else
|
39
|
-
puts ui.color('No application found!!!', :red)
|
40
|
-
exit(1)
|
23
|
+
def applications
|
24
|
+
@applications ||= begin
|
25
|
+
client.call.applications.all(machine.to_sym).last || []
|
41
26
|
end
|
42
27
|
end
|
43
28
|
|
@@ -53,27 +38,188 @@ module Capricorn::Helpers
|
|
53
38
|
end
|
54
39
|
end
|
55
40
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
41
|
+
def application_info
|
42
|
+
@application_info ||= begin
|
43
|
+
apps = applications
|
44
|
+
app = apps.detect do |app|
|
45
|
+
app[1] == application.last
|
46
|
+
end
|
47
|
+
|
48
|
+
unless app
|
49
|
+
halt 'Application not found!'
|
50
|
+
end
|
51
|
+
|
52
|
+
app
|
53
|
+
end
|
61
54
|
end
|
62
55
|
|
63
|
-
def
|
64
|
-
@
|
65
|
-
|
66
|
-
|
67
|
-
|
56
|
+
def application
|
57
|
+
@application ||= begin
|
58
|
+
application = nil
|
59
|
+
if options.application
|
60
|
+
application = options.application
|
61
|
+
elsif environment['application']
|
62
|
+
application = environment['application']
|
63
|
+
elsif application_ids.size == 1
|
64
|
+
application = application_ids.first
|
65
|
+
info "Selected default application: #{application}"
|
66
|
+
else
|
67
|
+
halt "Please select a application!"
|
68
|
+
end
|
69
|
+
|
70
|
+
if application
|
71
|
+
application = application_ids.abbrev[application]
|
72
|
+
end
|
73
|
+
|
74
|
+
unless application_ids.include?(application)
|
75
|
+
halt "I don't know this application!"
|
76
|
+
end
|
77
|
+
|
78
|
+
[machine, application]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def machine
|
83
|
+
@machine ||= begin
|
84
|
+
machine = nil
|
85
|
+
if options.machine
|
86
|
+
machine = options.machine
|
87
|
+
elsif environment['machine']
|
88
|
+
machine = environment['machine']
|
89
|
+
elsif machines.size == 1
|
90
|
+
machine = machines.first
|
91
|
+
info "Selected default machine: #{machine}"
|
92
|
+
else
|
93
|
+
halt "Please select a machine!"
|
94
|
+
end
|
95
|
+
|
96
|
+
if machine
|
97
|
+
machine = machines.abbrev[machine]
|
98
|
+
end
|
99
|
+
|
100
|
+
unless machines.include?(machine)
|
101
|
+
halt "I don't know this machine!"
|
102
|
+
end
|
103
|
+
|
104
|
+
machine
|
68
105
|
end
|
69
106
|
end
|
70
107
|
|
71
|
-
|
108
|
+
def node
|
109
|
+
@node ||= begin
|
110
|
+
node = nil
|
111
|
+
if options.machine
|
112
|
+
node = options.machine
|
113
|
+
elsif environment['machine']
|
114
|
+
node = environment['machine']
|
115
|
+
elsif nodes.size == 1
|
116
|
+
node = nodes.first
|
117
|
+
info "Selected default node: #{node}"
|
118
|
+
else
|
119
|
+
halt "Please select a node!"
|
120
|
+
end
|
121
|
+
|
122
|
+
if node
|
123
|
+
node = nodes.abbrev[node]
|
124
|
+
end
|
72
125
|
|
73
|
-
|
74
|
-
|
75
|
-
|
126
|
+
unless nodes.include?(node)
|
127
|
+
halt "I don't know this node!"
|
128
|
+
end
|
129
|
+
|
130
|
+
node
|
76
131
|
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def cluster
|
135
|
+
@cluster ||= begin
|
136
|
+
cluster = nil
|
137
|
+
if options.cluster
|
138
|
+
cluster = options.cluster
|
139
|
+
elsif environment['cluster']
|
140
|
+
cluster = environment['cluster']
|
141
|
+
elsif config.size == 1
|
142
|
+
cluster = config.keys.first
|
143
|
+
info "Selected default cluster: #{cluster}"
|
144
|
+
else
|
145
|
+
halt "Please select a cluster!"
|
146
|
+
end
|
147
|
+
|
148
|
+
if cluster
|
149
|
+
cluster = config.keys.abbrev[cluster]
|
150
|
+
end
|
151
|
+
|
152
|
+
unless config.keys.include?(cluster)
|
153
|
+
halt "I don't know this cluster!"
|
154
|
+
end
|
155
|
+
|
156
|
+
config[cluster]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def environment
|
161
|
+
@environment ||= begin
|
162
|
+
environment = nil
|
163
|
+
if options.environment
|
164
|
+
environment = options.environment
|
165
|
+
elsif local_config.size == 1
|
166
|
+
environment = local_config.keys.first
|
167
|
+
info "Selected default environment: #{environment}"
|
168
|
+
elsif local_config.size > 1
|
169
|
+
halt "Please select an environment!"
|
170
|
+
end
|
171
|
+
|
172
|
+
if environment
|
173
|
+
environment = local_config.keys.abbrev[environment]
|
174
|
+
end
|
175
|
+
|
176
|
+
config = nil
|
177
|
+
if environment.nil?
|
178
|
+
config = {}
|
179
|
+
elsif local_config.keys.include?(environment)
|
180
|
+
config = local_config[environment]
|
181
|
+
else
|
182
|
+
halt "I don't know this environment!"
|
183
|
+
end
|
184
|
+
config
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def local_config
|
189
|
+
@local_config ||= begin
|
190
|
+
if File.file?('.capricorn.yml')
|
191
|
+
YAML.load_file('.capricorn.yml')
|
192
|
+
else
|
193
|
+
{}
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def config
|
199
|
+
@config ||= begin
|
200
|
+
config_path = File.expand_path('~/.capricorn/config.yml')
|
201
|
+
unless File.file?(config_path)
|
202
|
+
FileUtils.mkdir_p(File.dirname(config_path))
|
203
|
+
File.open(config_path, 'w+', 0600) { |file| file.write DEFAULT_CONFIG }
|
204
|
+
info "Please edit your config file in ~/.capricorn/config.yml"
|
205
|
+
exit 2
|
206
|
+
end
|
207
|
+
YAML.load_file(config_path)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def client
|
212
|
+
host = (cluster['host'] || 'localhost').to_s
|
213
|
+
port = (cluster['port'] || 3457).to_i
|
214
|
+
@client ||= BERTRPC::Service.new(host, port)
|
215
|
+
end
|
216
|
+
|
217
|
+
def info(msg)
|
218
|
+
shell.say_status('Info', msg)
|
219
|
+
end
|
77
220
|
|
221
|
+
def halt(msg, continue=false)
|
222
|
+
shell.say_status('Error', msg, :red)
|
223
|
+
exit(1) unless continue
|
78
224
|
end
|
79
225
|
end
|
data/lib/capricorn/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capricorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 2.0.
|
9
|
+
- 7
|
10
|
+
version: 2.0.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Simon Menke
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-06-
|
18
|
+
date: 2010-06-11 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -35,83 +35,83 @@ dependencies:
|
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
38
|
+
name: mustache
|
39
39
|
prerelease: false
|
40
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - "="
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
45
|
+
hash: 9
|
46
46
|
segments:
|
47
|
-
-
|
47
|
+
- 0
|
48
48
|
- 5
|
49
|
-
-
|
50
|
-
version:
|
49
|
+
- 1
|
50
|
+
version: 0.5.1
|
51
51
|
type: :runtime
|
52
52
|
version_requirements: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
54
|
+
name: rush
|
55
55
|
prerelease: false
|
56
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
59
|
- - "="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
hash:
|
61
|
+
hash: 13
|
62
62
|
segments:
|
63
63
|
- 0
|
64
|
+
- 6
|
64
65
|
- 5
|
65
|
-
|
66
|
-
version: 0.5.1
|
66
|
+
version: 0.6.5
|
67
67
|
type: :runtime
|
68
68
|
version_requirements: *id003
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: session
|
71
71
|
prerelease: false
|
72
72
|
requirement: &id004 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - "="
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
hash:
|
77
|
+
hash: 3
|
78
78
|
segments:
|
79
|
+
- 3
|
80
|
+
- 1
|
79
81
|
- 0
|
80
|
-
|
81
|
-
- 5
|
82
|
-
version: 0.6.5
|
82
|
+
version: 3.1.0
|
83
83
|
type: :runtime
|
84
84
|
version_requirements: *id004
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
|
-
name:
|
86
|
+
name: thor
|
87
87
|
prerelease: false
|
88
88
|
requirement: &id005 !ruby/object:Gem::Requirement
|
89
89
|
none: false
|
90
90
|
requirements:
|
91
91
|
- - "="
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
hash:
|
93
|
+
hash: 39
|
94
94
|
segments:
|
95
|
-
- 3
|
96
|
-
- 1
|
97
95
|
- 0
|
98
|
-
|
96
|
+
- 13
|
97
|
+
- 6
|
98
|
+
version: 0.13.6
|
99
99
|
type: :runtime
|
100
100
|
version_requirements: *id005
|
101
101
|
- !ruby/object:Gem::Dependency
|
102
|
-
name:
|
102
|
+
name: public_suffix_service
|
103
103
|
prerelease: false
|
104
104
|
requirement: &id006 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - "="
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
hash:
|
109
|
+
hash: 15
|
110
110
|
segments:
|
111
111
|
- 0
|
112
|
-
-
|
113
|
-
-
|
114
|
-
version: 0.
|
112
|
+
- 4
|
113
|
+
- 0
|
114
|
+
version: 0.4.0
|
115
115
|
type: :runtime
|
116
116
|
version_requirements: *id006
|
117
117
|
description: Build, manage and configure many railsish web applications.
|
@@ -134,6 +134,8 @@ files:
|
|
134
134
|
- lib/capricorn/recipes/macports.rb
|
135
135
|
- lib/capricorn/system_context.rb
|
136
136
|
- lib/capricorn/version.rb
|
137
|
+
- lib/capricorn-client/cli/applications/domains.rb
|
138
|
+
- lib/capricorn-client/cli/applications/gems.rb
|
137
139
|
- lib/capricorn-client/cli/applications.rb
|
138
140
|
- lib/capricorn-client/cli/gems.rb
|
139
141
|
- lib/capricorn-client/cli/machines.rb
|