cf 0.1.2 → 0.1.3

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.
@@ -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