capricorn 2.0.6 → 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,4 +7,4 @@ rescue LoadError
7
7
  require 'capricorn-client'
8
8
  end
9
9
 
10
- Capricorn::Runner.start
10
+ Capricorn::CLI.start
@@ -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
- module CLI
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
- @cluster = config[cluster_name]
46
- unless @cluster
47
- puts "I don't know this cluster"
48
- exit 1
49
- end
18
+ def self.banner(task)
19
+ "#{banner_base} #{task.formatted_usage(self, true)}"
20
+ end
50
21
 
51
- case ARGV.shift
52
- when 'applications'
53
- Capricorn::CLI::Applications.start
54
- when 'gems'
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
- help
27
+ super
60
28
  end
61
29
  end
62
30
 
63
- def help
64
- puts HELP
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
- def cluster
68
- @cluster
69
- end
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
- def config
72
- @config ||= begin
73
- config_path = File.expand_path('~/.capricorn/config.yml')
74
- unless File.file?(config_path)
75
- FileUtils.mkdir_p(File.dirname(config_path))
76
- File.open(config_path, 'w+', 0600) { |file| file.write DEFAULT_CONFIG }
77
- puts "Please edit your config file in ~/.capricorn/config.yml"
78
- exit 2
79
- end
80
- YAML.load_file(config_path)
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 < Thor
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[1], app[3]]
30
+ [app[3], app[1]]
11
31
  end
12
- apps.flatten!
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
- environment = ui.choose do |q|
31
- q.choices(*%w( production development staging testing ))
32
- q.prompt = "environment: "
33
- q.default = 'production'
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
- domains = []
36
- domains << ui.ask("domain: ") do |q|
37
- q.validate = /^[\w\d]+(\.[\w\d]+)*$/
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
- loop do
40
- domain = ui.ask("more: ") do |q|
41
- q.validate = /^([\w\d]+(\.[\w\d]+)*)?$/
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
- break if domain.strip.empty?
44
- domains << domain
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
- puts ui.color('This doesn\'t appear to be a milkshake app!', :red)
62
- puts ui.color('no milkshake config was found', :red)
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
- puts ui.color('This doesn\'t appear to be a milkshake app!', :red)
68
- puts ui.color('no shared dir was found', :red)
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
- puts ui.color('This doesn\'t appear to be a milkshake app!', :red)
76
- puts ui.color('no gems were found', :red)
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
- puts ui.color('This doesn\'t appear to be a milkshake app!', :red)
83
- puts ui.color('no environment.rb was found', :red)
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
- puts ui.color('This doesn\'t appear to be a milkshake app!', :red)
90
- puts ui.color('no uid was found', :red)
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
- puts ui.color('This doesn\'t appear to be a milkshake app!', :red)
97
- puts ui.color('no gid was found', :red)
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
- domains = []
111
- domains << ui.ask("domain: ") do |q|
112
- q.validate = /^[\w\d]+(\.[\w\d]+)*$/
123
+
124
+ name = name.to_s.strip
125
+ if name.empty?
126
+ halt "Please choose a name!"
113
127
  end
114
- loop do
115
- domain = ui.ask("more: ") do |q|
116
- q.validate = /^([\w\d]+(\.[\w\d]+)*)?$/
117
- end
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
- p client.call.applications.import(machine.to_sym, name, domains, environment, root, gems, uid, gid)
129
- end
130
-
131
- desc "update", "update an application on MACHINE"
132
- def update
133
- machine, id = *select_application
134
- app = find_app(machine, id)
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 = *select_application
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 = *select_application
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 = *select_application
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 = *select_application
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 = *select_application
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 < Thor
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
- puts ui.color("Pushed: #{File.basename(path)}", :green)
15
+ info "Pushed: #{File.basename(path)}"
13
16
  rescue BERTRPC::UserError => e
14
- puts ui.color(e.message, :red)
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
- ui.table %w( Gem Requirements ), clean_missing(client.call.gems.missing), :columns_across, 2
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
- ui.table %w( Gem Versions ), clean_all(client.call.gems.all), :columns_across, 2
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
- [name, versions.join(', ')]
40
- end.flatten
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.flatten
76
+ end
55
77
  end
56
-
78
+
57
79
  end
@@ -1,20 +1,29 @@
1
- class Capricorn::CLI::Machines < Thor
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
- ui.table("Machines", self.machines)
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 [NODE]", "reboot a node"
10
- def reboot(node=nil)
11
- node ||= select_node
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 [NODE]", "update a node"
16
- def selfupdate(node=nil)
17
- node ||= select_node
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
- def select_machine
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
- def select_node
15
- if self.nodes.size > 1
16
- ui.choose(*self.nodes)
17
- elsif self.nodes.size == 1 and ui.agree("Use nodes #{self.nodes.first}? ")
18
- self.nodes.first
19
- else
20
- puts ui.color('No nodes found!!!', :red)
21
- exit(1)
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 select_application
26
- machine = select_machine
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 client
57
- cluster = Capricorn::Runner.cluster
58
- host = (cluster['host'] || 'localhost').to_s
59
- port = (cluster['port'] || 3457).to_i
60
- @client ||= BERTRPC::Service.new(host, port)
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 ui
64
- @ui ||= begin
65
- @ui = HighLine.new
66
- @ui.extend UI
67
- @ui
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
- module UI
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
- def table(headers, items, mode=:rows, option=nil)
74
- headers = [headers].flatten.collect { |h| color(h, :green) }
75
- @output.puts list(headers+items, mode, option)
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
@@ -1,5 +1,5 @@
1
1
  module Capricorn
2
2
 
3
- VERSION = '2.0.6'
3
+ VERSION = '2.0.7'
4
4
 
5
5
  end
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: 3
4
+ hash: 1
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 6
10
- version: 2.0.6
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-10 00:00:00 +02:00
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: highline
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: 7
45
+ hash: 9
46
46
  segments:
47
- - 1
47
+ - 0
48
48
  - 5
49
- - 2
50
- version: 1.5.2
49
+ - 1
50
+ version: 0.5.1
51
51
  type: :runtime
52
52
  version_requirements: *id002
53
53
  - !ruby/object:Gem::Dependency
54
- name: mustache
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: 9
61
+ hash: 13
62
62
  segments:
63
63
  - 0
64
+ - 6
64
65
  - 5
65
- - 1
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: rush
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: 13
77
+ hash: 3
78
78
  segments:
79
+ - 3
80
+ - 1
79
81
  - 0
80
- - 6
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: session
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: 3
93
+ hash: 39
94
94
  segments:
95
- - 3
96
- - 1
97
95
  - 0
98
- version: 3.1.0
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: thor
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: 41
109
+ hash: 15
110
110
  segments:
111
111
  - 0
112
- - 12
113
- - 3
114
- version: 0.12.3
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