cf 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,8 @@ require "cf/cli/user"
5
5
 
6
6
  module CF
7
7
  class CLI < App # subclass App since we operate on Apps by default
8
+ class_option :proxy, :aliases => "-u", :desc => "Proxy user"
9
+
8
10
  class_option :verbose,
9
11
  :type => :boolean, :aliases => "-v", :desc => "Verbose"
10
12
 
@@ -95,17 +97,20 @@ module CF
95
97
  puts "target: #{b(client.target)}"
96
98
  puts " version: #{info["version"]}"
97
99
  puts " support: #{info["support"]}"
98
- puts ""
99
- puts "user: #{b(info["user"])}"
100
- puts " usage:"
101
-
102
- limits = info["limits"]
103
- info["usage"].each do |k, v|
104
- m = limits[k]
105
- if k == "memory"
106
- puts " #{k}: #{usage(v * 1024 * 1024, m * 1024 * 1024)}"
107
- else
108
- puts " #{k}: #{b(v)} of #{b(m)} limit"
100
+
101
+ if info["user"]
102
+ puts ""
103
+ puts "user: #{b(info["user"])}"
104
+ puts " usage:"
105
+
106
+ limits = info["limits"]
107
+ info["usage"].each do |k, v|
108
+ m = limits[k]
109
+ if k == "memory"
110
+ puts " #{k}: #{usage(v * 1024 * 1024, m * 1024 * 1024)}"
111
+ else
112
+ puts " #{k}: #{b(v)} of #{b(m)} limit"
113
+ end
109
114
  end
110
115
  end
111
116
  end
@@ -23,6 +23,25 @@ module CF
23
23
  end
24
24
  end
25
25
 
26
+ desc "health ...APPS", "Get application health"
27
+ def health(*names)
28
+ apps =
29
+ with_progress("Getting application health") do
30
+ names.collect do |n|
31
+ [n, app_status(client.app(n))]
32
+ end
33
+ end
34
+
35
+ apps.each do |name, status|
36
+ unless simple_output?
37
+ puts ""
38
+ print "#{c(name, :blue)}: "
39
+ end
40
+
41
+ puts status
42
+ end
43
+ end
44
+
26
45
  desc "stop [APP]", "Stop an application"
27
46
  def stop(name)
28
47
  with_progress("Stopping #{c(name, :blue)}") do |s|
@@ -274,7 +293,7 @@ module CF
274
293
  err "The 'update' command is no longer used; use 'push' instead."
275
294
  end
276
295
 
277
- desc "stats", "Display application instance status"
296
+ desc "stats [APP]", "Display application instance status"
278
297
  def stats(name)
279
298
  stats =
280
299
  with_progress("Getting stats") do
@@ -500,6 +519,16 @@ module CF
500
519
  end
501
520
  end
502
521
 
522
+ def app_status(a)
523
+ health = a.health
524
+
525
+ if a.debug_mode == "suspend" && health == "0%"
526
+ c("suspended", :yellow)
527
+ else
528
+ c(health.downcase, state_color(health))
529
+ end
530
+ end
531
+
503
532
  def display_app(a)
504
533
  if simple_output?
505
534
  puts a.name
@@ -508,13 +537,7 @@ module CF
508
537
 
509
538
  puts ""
510
539
 
511
- health = a.health
512
-
513
- if a.debug_mode == "suspend" && health == "0%"
514
- status = c("suspended", :yellow)
515
- else
516
- status = c(health.downcase, state_color(health))
517
- end
540
+ status = app_status(a)
518
541
 
519
542
  print "#{c(a.name, :blue)}: #{status}"
520
543
 
@@ -1,6 +1,6 @@
1
1
  require "thor"
2
2
  require "interact"
3
- require "json/pure"
3
+ require "yaml"
4
4
 
5
5
  require "cfoundry"
6
6
 
@@ -357,7 +357,7 @@ module CF
357
357
  end
358
358
 
359
359
  def tokens
360
- JSON.parse(File.read(tokens_file))
360
+ YAML.load_file(tokens_file)
361
361
  end
362
362
 
363
363
  def client_token
@@ -367,8 +367,8 @@ module CF
367
367
  def save_tokens(ts)
368
368
  ensure_config_dir
369
369
 
370
- File.open(File.expand_path(CF::TOKENS_FILE), "w") do |f|
371
- f.write ts.to_json
370
+ File.open(File.expand_path(CF::TOKENS_FILE), "w") do |io|
371
+ YAML.dump(ts, io)
372
372
  end
373
373
  end
374
374
 
@@ -385,7 +385,11 @@ module CF
385
385
  end
386
386
 
387
387
  def client
388
- @client ||= CFoundry::Client.new(client_target, client_token)
388
+ return @client if @client
389
+
390
+ @client = CFoundry::Client.new(client_target, client_token)
391
+ @client.proxy = options[:proxy]
392
+ @client
389
393
  end
390
394
 
391
395
  def usage(used, limit)
@@ -69,9 +69,12 @@ module CF
69
69
  }
70
70
 
71
71
  # colored text
72
- def c(str, color, bright = true)
72
+ #
73
+ # shouldn't use bright colors, as some color themes abuse
74
+ # the bright palette (I'm looking at you, Solarized)
75
+ def c(str, color)
73
76
  return str unless color?
74
- "\e[#{bright ? 9 : 3}#{COLOR_CODES[color]}m#{str}\e[0m"
77
+ "\e[3#{COLOR_CODES[color]}m#{str}\e[0m"
75
78
  end
76
79
  module_function :c
77
80
 
@@ -3,8 +3,8 @@ module CF
3
3
  OLD_TOKENS_FILE = "~/.vmc_token"
4
4
 
5
5
  CONFIG_DIR = "~/.cf"
6
- PLUGINS_DIR = "#{CONFIG_DIR}/plugins"
6
+ PLUGINS_FILE = "#{CONFIG_DIR}/plugins.yml"
7
7
  TARGET_FILE = "#{CONFIG_DIR}/target"
8
- TOKENS_FILE = "#{CONFIG_DIR}/tokens"
8
+ TOKENS_FILE = "#{CONFIG_DIR}/tokens.yml"
9
9
  CRASH_FILE = "#{CONFIG_DIR}/crash"
10
10
  end
@@ -16,6 +16,10 @@ module CF
16
16
  matches = {}
17
17
  all_frameworks.each do |name, meta|
18
18
  matched = false
19
+
20
+ # e.g. standalone has no detection
21
+ next if meta["detection"].nil?
22
+
19
23
  meta["detection"].first.each do |file, match|
20
24
  files =
21
25
  if File.file? @path
@@ -1,3 +1,6 @@
1
+ require "set"
2
+ require "yaml"
3
+
1
4
  require "cf/constants"
2
5
  require "cf/cli"
3
6
 
@@ -6,13 +9,26 @@ module CF
6
9
  @@plugins = []
7
10
 
8
11
  def self.load_all
9
- bundled = File.expand_path("../../../plugins/*/main.rb", __FILE__)
10
- Dir.glob(bundled).each do |main|
11
- require main
12
+ # auto-load gems with 'vmc-plugin' in their name
13
+ enabled =
14
+ Set.new(
15
+ Gem::Specification.find_all { |s|
16
+ s.name =~ /vmc-plugin/
17
+ }.collect(&:name))
18
+
19
+ # allow explicit enabling/disabling of gems via config
20
+ plugins = File.expand_path(CF::PLUGINS_FILE)
21
+ if File.exists?(plugins) && yaml = YAML.load_file(plugins)
22
+ enabled += yaml["enabled"] if yaml["enabled"]
23
+ enabled -= yaml["disabled"] if yaml["disabled"]
12
24
  end
13
25
 
14
- Dir.glob(File.expand_path("#{CF::PLUGINS_DIR}/*/main.rb")).each do |main|
15
- require main
26
+ # load up each gem's 'plugin' file
27
+ #
28
+ # we require this file specifically so people can require the gem
29
+ # without it plugging into CF
30
+ enabled.each do |gemname|
31
+ require "#{gemname}/plugin"
16
32
  end
17
33
  end
18
34
  end
@@ -1,3 +1,3 @@
1
1
  module CF
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,68 +1,96 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: cf
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 3
10
+ version: 0.1.3
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Alex Suraci
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-04-05 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-05-01 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: interact
16
- requirement: &70204736023380 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
25
+ requirements:
19
26
  - - ~>
20
- - !ruby/object:Gem::Version
27
+ - !ruby/object:Gem::Version
28
+ hash: 13
29
+ segments:
30
+ - 0
31
+ - 4
32
+ - 1
21
33
  version: 0.4.1
22
34
  type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: cfoundry
23
38
  prerelease: false
24
- version_requirements: *70204736023380
25
- - !ruby/object:Gem::Dependency
26
- name: json_pure
27
- requirement: &70204736022880 !ruby/object:Gem::Requirement
39
+ requirement: &id002 !ruby/object:Gem::Requirement
28
40
  none: false
29
- requirements:
41
+ requirements:
30
42
  - - ~>
31
- - !ruby/object:Gem::Version
32
- version: 1.6.5
43
+ - !ruby/object:Gem::Version
44
+ hash: 27
45
+ segments:
46
+ - 0
47
+ - 1
48
+ - 0
49
+ version: 0.1.0
33
50
  type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: thor
34
54
  prerelease: false
35
- version_requirements: *70204736022880
36
- - !ruby/object:Gem::Dependency
37
- name: cfoundry
38
- requirement: &70204736022420 !ruby/object:Gem::Requirement
55
+ requirement: &id003 !ruby/object:Gem::Requirement
39
56
  none: false
40
- requirements:
57
+ requirements:
41
58
  - - ~>
42
- - !ruby/object:Gem::Version
43
- version: 0.1.0
59
+ - !ruby/object:Gem::Version
60
+ hash: 43
61
+ segments:
62
+ - 0
63
+ - 14
64
+ - 6
65
+ version: 0.14.6
44
66
  type: :runtime
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: manifests-vmc-plugin
45
70
  prerelease: false
46
- version_requirements: *70204736022420
47
- - !ruby/object:Gem::Dependency
48
- name: thor
49
- requirement: &70204736021940 !ruby/object:Gem::Requirement
71
+ requirement: &id004 !ruby/object:Gem::Requirement
50
72
  none: false
51
- requirements:
73
+ requirements:
52
74
  - - ~>
53
- - !ruby/object:Gem::Version
54
- version: 0.14.6
75
+ - !ruby/object:Gem::Version
76
+ hash: 27
77
+ segments:
78
+ - 0
79
+ - 1
80
+ - 0
81
+ version: 0.1.0
55
82
  type: :runtime
56
- prerelease: false
57
- version_requirements: *70204736021940
83
+ version_requirements: *id004
58
84
  description:
59
- email:
85
+ email:
60
86
  - asuraci@vmware.com
61
- executables:
87
+ executables:
62
88
  - cf
63
89
  extensions: []
90
+
64
91
  extra_rdoc_files: []
65
- files:
92
+
93
+ files:
66
94
  - LICENSE
67
95
  - Rakefile
68
96
  - lib/cf/cli/app.rb
@@ -76,30 +104,39 @@ files:
76
104
  - lib/cf/plugin.rb
77
105
  - lib/cf/version.rb
78
106
  - lib/cf.rb
79
- - plugins/manifests/main.rb
80
107
  - bin/cf
81
108
  homepage: http://cloudfoundry.com/
82
109
  licenses: []
110
+
83
111
  post_install_message:
84
112
  rdoc_options: []
85
- require_paths:
113
+
114
+ require_paths:
86
115
  - lib
87
- required_ruby_version: !ruby/object:Gem::Requirement
116
+ required_ruby_version: !ruby/object:Gem::Requirement
88
117
  none: false
89
- requirements:
90
- - - ! '>='
91
- - !ruby/object:Gem::Version
92
- version: '0'
93
- required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
126
  none: false
95
- requirements:
96
- - - ! '>='
97
- - !ruby/object:Gem::Version
98
- version: '0'
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
133
+ version: "0"
99
134
  requirements: []
135
+
100
136
  rubyforge_project: cf
101
- rubygems_version: 1.8.10
137
+ rubygems_version: 1.8.23
102
138
  signing_key:
103
139
  specification_version: 3
104
140
  summary: Friendly command-line interface for Cloud Foundry.
105
141
  test_files: []
142
+
@@ -1,508 +0,0 @@
1
- require "yaml"
2
- require "set"
3
- require "cf/plugin"
4
-
5
- CF.Plugin do
6
- class_option :manifest,
7
- :aliases => "-m", :desc => "Manifest file"
8
-
9
- class_option :path,
10
- :aliases => "-p", :desc => "Application path"
11
- end
12
-
13
- module CF::Plugins
14
- module Manifests
15
- MANIFEST_FILE = "manifest.yml"
16
-
17
- def manifest
18
- return @manifest if @manifest
19
-
20
- if manifest_file && File.exists?(manifest_file)
21
- @manifest = load_manifest(manifest_file)
22
- end
23
- end
24
-
25
- def save_manifest(save_to = manifest_file)
26
- err "No manifest to save!" unless @manifest
27
-
28
- File.open(save_to, "w") do |io|
29
- YAML.dump(@manifest, io)
30
- end
31
- end
32
-
33
- # find the manifest file to work with
34
- def manifest_file
35
- return options[:manifest] if options[:manifest]
36
- return @manifest_file if @manifest_file
37
-
38
- where = Dir.pwd
39
- while true
40
- if File.exists?(File.join(where, MANIFEST_FILE))
41
- @manifest_file = File.join(where, MANIFEST_FILE)
42
- break
43
- elsif File.basename(where) == "/"
44
- @manifest_file = nil
45
- break
46
- else
47
- where = File.expand_path("../", where)
48
- end
49
- end
50
-
51
- @manifest_file
52
- end
53
-
54
- # load and resolve a given manifest file
55
- def load_manifest(file)
56
- manifest = build_manifest(file)
57
- resolve_manifest(manifest)
58
- manifest
59
- end
60
-
61
- # parse a manifest and merge with its inherited manifests
62
- def build_manifest(file)
63
- manifest = YAML.load_file file
64
-
65
- Array(manifest["inherit"]).each do |p|
66
- manifest = merge_parent(manifest, p)
67
- end
68
-
69
- manifest
70
- end
71
-
72
- # merge the manifest at `path' into the `child'
73
- def merge_parent(child, path)
74
- file = File.expand_path("../" + path, manifest_file)
75
- merge_manifest(child, build_manifest(file))
76
- end
77
-
78
- # deep hash merge
79
- def merge_manifest(child, parent)
80
- merge = proc do |_, old, new|
81
- if new.is_a?(Hash) and old.is_a?(Hash)
82
- old.merge(new, &merge)
83
- else
84
- new
85
- end
86
- end
87
-
88
- parent.merge(child, &merge)
89
- end
90
-
91
- # resolve symbols in a manifest
92
- def resolve_manifest(manifest)
93
- if apps = manifest["applications"]
94
- apps.each_value do |v|
95
- resolve_lexically(v, [manifest])
96
- end
97
- end
98
-
99
- resolve_lexically(manifest, [manifest])
100
-
101
- nil
102
- end
103
-
104
- # resolve symbols, with hashes introducing new lexical symbols
105
- def resolve_lexically(val, ctx)
106
- case val
107
- when Hash
108
- val.each_value do |v|
109
- resolve_lexically(v, [val] + ctx)
110
- end
111
- when Array
112
- val.each do |v|
113
- resolve_lexically(v, ctx)
114
- end
115
- when String
116
- val.gsub!(/\$\{([[:alnum:]\-]+)\}/) do
117
- resolve_symbol($1, ctx)
118
- end
119
- end
120
-
121
- nil
122
- end
123
-
124
- # resolve a symbol to its value, and then resolve that value
125
- def resolve_symbol(sym, ctx)
126
- case sym
127
- when "target-url"
128
- target_url(ctx)
129
-
130
- when "target-base"
131
- target_url(ctx).sub(/^[^\.]+\./, "")
132
-
133
- when "random-word"
134
- "%04x" % [rand(0x0100000)]
135
-
136
- else
137
- found = find_symbol(sym, ctx)
138
-
139
- if found
140
- resolve_lexically(found, ctx)
141
- found
142
- else
143
- err("Unknown symbol in manifest: #{sym}")
144
- end
145
- end
146
- end
147
-
148
- # get the target url from either the manifest or the current client
149
- def target_url(ctx = [])
150
- find_symbol("target", ctx) || client_target
151
- end
152
-
153
- # search for a symbol introduced in the lexical context
154
- def find_symbol(sym, ctx)
155
- ctx.each do |h|
156
- if val = resolve_in(h, sym)
157
- return val
158
- end
159
- end
160
-
161
- nil
162
- end
163
-
164
- # find a value, searching in explicit properties first
165
- def resolve_in(hash, *where)
166
- find_in_hash(hash, ["properties"] + where) ||
167
- find_in_hash(hash, where)
168
- end
169
-
170
- # helper for following a path of values in a hash
171
- def find_in_hash(hash, where)
172
- what = hash
173
- where.each do |x|
174
- return nil unless what.is_a?(Hash)
175
- what = what[x]
176
- end
177
-
178
- what
179
- end
180
-
181
- MANIFEST_META = ["applications", "properties"]
182
-
183
- def toplevel_attributes
184
- if m = manifest
185
- m.reject do |k, _|
186
- MANIFEST_META.include? k
187
- end
188
- end
189
- end
190
-
191
- def app_info(find_path)
192
- return unless manifest and manifest["applications"]
193
-
194
- manifest["applications"].each do |path, info|
195
- app = File.expand_path("../" + path, manifest_file)
196
- if find_path == app
197
- return toplevel_attributes.merge info
198
- end
199
- end
200
-
201
- nil
202
- end
203
-
204
- # call a block for each app in a manifest (in dependency order), setting
205
- # inputs for each app
206
- def each_app
207
- given_path = passed_value(:path)
208
-
209
- if manifest and all_apps = manifest["applications"]
210
- # given a specific application
211
- if given_path
212
- full_path = File.expand_path(given_path)
213
-
214
- if info = app_info(full_path)
215
- with_app(full_path, info) do
216
- yield info
217
- end
218
- else
219
- raise "Path #{given_path} is not described by the manifest."
220
- end
221
- else
222
- # all apps in the manifest
223
- ordered_by_deps(all_apps).each do |path|
224
- app = File.expand_path("../" + path, manifest_file)
225
- info = app_info(app)
226
-
227
- with_app(app, info) do
228
- yield info
229
- end
230
- end
231
- end
232
-
233
- true
234
-
235
- # manually created or legacy single-app manifest
236
- elsif single = toplevel_attributes
237
- with_app(full_path || ".", single) do
238
- yield single
239
- end
240
-
241
- true
242
-
243
- else
244
- false
245
- end
246
- end
247
-
248
- private
249
-
250
- def inputs
251
- @inputs ||= {}
252
- end
253
-
254
- # call the block as if the app info and path were given as flags
255
- def with_app(path, info)
256
- before_path = inputs[:path]
257
- before_info = {}
258
-
259
- inputs[:path] = path
260
-
261
- info.each do |k, v|
262
- before_info[k.to_sym] = inputs[k.to_sym]
263
- inputs[k.to_sym] = v
264
- end
265
-
266
- yield
267
- ensure
268
- if before_path.nil?
269
- inputs.delete :path
270
- else
271
- inputs[:path] = before_path
272
- end
273
-
274
- before_info.each do |k, v|
275
- if v.nil?
276
- inputs.delete k
277
- else
278
- inputs[k] = v
279
- end
280
- end
281
- end
282
-
283
- # sort applications in dependency order
284
- # e.g. if A depends on B, B will be listed before A
285
- def ordered_by_deps(apps, abspaths = nil, processed = Set[])
286
- unless abspaths
287
- abspaths = {}
288
- apps.each do |p, i|
289
- ep = File.expand_path("../" + p, manifest_file)
290
- abspaths[ep] = i
291
- end
292
- end
293
-
294
- ordered = []
295
- apps.each do |path, info|
296
- epath = File.expand_path("../" + path, manifest_file)
297
-
298
- if deps = info["depends-on"]
299
- dep_apps = {}
300
- deps.each do |dep|
301
- edep = File.expand_path("../" + dep, manifest_file)
302
-
303
- err "Circular dependency detected." if processed.include? edep
304
-
305
- dep_apps[dep] = abspaths[edep]
306
- end
307
-
308
- processed.add(epath)
309
-
310
- ordered += ordered_by_deps(dep_apps, abspaths, processed)
311
- ordered << path
312
- elsif not processed.include? epath
313
- ordered << path
314
- processed.add(epath)
315
- end
316
- end
317
-
318
- ordered
319
- end
320
-
321
- # detect changes in app info, and update the app if necessary.
322
- #
323
- # redeploys the app if necessary (after prompting the user), e.g. for
324
- # runtime/framework change
325
- def sync_changes(info)
326
- app = client.app(info["name"])
327
- return unless app.exists?
328
-
329
- diff = {}
330
- need_restage = []
331
- info.each do |k, v|
332
- case k
333
- when /ur[li]s?/
334
- old = app.urls
335
- if old != Array(v)
336
- diff[k] = [old, v]
337
- app.urls = Array(v)
338
- end
339
- when "env"
340
- old = app.env
341
- if old != v
342
- diff[k] = [old, v]
343
- app.env = v
344
- end
345
- when "framework", "runtime"
346
- old = app.send(k)
347
- if old != v
348
- diff[k] = [old, v]
349
- app.send(:"#{k}=", v)
350
- need_restage << k
351
- end
352
- when "instances"
353
- old = app.total_instances
354
- if old != v
355
- diff[k] = [old, v]
356
- app.total_instances = v
357
- end
358
- when "mem", "memory"
359
- old = app.memory
360
- new = megabytes(v)
361
- if old != new
362
- diff[k] = [old, new]
363
- app.memory = new
364
- end
365
- end
366
- end
367
-
368
- return if diff.empty?
369
-
370
- unless simple_output?
371
- puts "Detected the following changes to #{c(app.name, :blue)}:"
372
- diff.each do |k, d|
373
- old, new = d
374
- label = c(k, need_restage.include?(k) ? :red : :green)
375
- puts " #{label}: #{old.inspect} #{c("->", :black)} #{new.inspect}"
376
- end
377
-
378
- puts ""
379
- end
380
-
381
- if need_restage.empty?
382
- with_progress("Updating #{c(app.name, :blue)}") do
383
- app.update!
384
- end
385
- else
386
- unless simple_output?
387
- puts "The following changes require the app to be recreated:"
388
- need_restage.each do |n|
389
- puts " #{c(n, :magenta)}"
390
- end
391
- puts ""
392
- end
393
-
394
- if force? || ask("Redeploy?", :default => false)
395
- with_progress("Deleting #{c(app.name, :blue)}") do
396
- app.delete!
397
- end
398
-
399
- with_progress("Recreating #{c(app.name, :blue)}") do
400
- app.create!
401
- end
402
- end
403
- end
404
- end
405
- end
406
- end
407
-
408
- CF.Plugin(CF::App) do
409
- include CF::Plugins::Manifests
410
-
411
- # basic commands that, when given no args, act on the
412
- # app(s) described by the manifest, in dependency-order
413
- [:start, :instances, :logs].each do |wrap|
414
- around(wrap) do |cmd, args|
415
- if args.empty?
416
- each_app do |a|
417
- cmd.call(a["name"])
418
- puts "" unless simple_output?
419
- end || err("No applications to act on.")
420
- else
421
- cmd.call(args)
422
- end
423
- end
424
- end
425
-
426
- # same as above but in reverse dependency-order
427
- [:stop, :delete].each do |wrap|
428
- around(wrap) do |cmd, args|
429
- if args.empty?
430
- reversed = []
431
- each_app do |a|
432
- reversed.unshift a["name"]
433
- end || err("No applications to act on.")
434
-
435
- reversed.each do |name|
436
- cmd.call(name)
437
- puts "" unless simple_output?
438
- end
439
- else
440
- cmd.call(args)
441
- end
442
- end
443
- end
444
-
445
- # stop apps in reverse dependency order,
446
- # and then start in dependency order
447
- around(:restart) do |cmd, args|
448
- if args.empty?
449
- reversed = []
450
- forwards = []
451
- each_app do |a|
452
- reversed.unshift a["name"]
453
- forwards << a["name"]
454
- end || err("No applications to act on.")
455
-
456
- reversed.each do |name|
457
- stop(name)
458
- end
459
-
460
- puts "" unless simple_output?
461
-
462
- forwards.each do |name|
463
- start(name)
464
- end
465
- else
466
- cmd.call(args)
467
- end
468
- end
469
-
470
- # push and sync meta changes in the manifest
471
- # also sets env data on creation if present in manifest
472
- around(:push) do |push, args|
473
- if args.empty?
474
- all_pushed =
475
- each_app do |a|
476
- app = client.app(a["name"])
477
- updating = app.exists?
478
-
479
- start = input(:start)
480
-
481
- begin
482
- inputs[:start] = false
483
-
484
- sync_changes(a)
485
- push.call(a["name"])
486
-
487
- unless updating
488
- app.env = a["env"]
489
-
490
- if start
491
- start(a["name"])
492
- else
493
- app.update!
494
- end
495
- end
496
- ensure
497
- inputs[:start] = start
498
- end
499
-
500
- puts "" unless simple_output?
501
- end
502
-
503
- push.call unless all_pushed
504
- else
505
- push.call(args)
506
- end
507
- end
508
- end