manifests-vmc-plugin 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,161 +1,100 @@
1
1
  require "vmc/plugin"
2
2
  require "manifests-vmc-plugin"
3
3
 
4
- VMC.Plugin do
5
- class_option :manifest,
6
- :aliases => "-m", :desc => "Manifest file"
7
4
 
8
- class_option :path,
9
- :aliases => "-p", :desc => "Application path"
10
- end
11
-
12
- VMC.Plugin(VMC::App) do
5
+ class Manifests < VMC::CLI
13
6
  include VMCManifests
14
7
 
15
- # basic commands that, when given no args, act on the
16
- # app(s) described by the manifest, in dependency-order
17
- [:start, :instances, :logs, :file, :files, :health, :stats].each do |wrap|
18
- around(wrap) do |cmd, args|
19
- if args.empty? && !passed_value(:name)
20
- each_app do |a|
21
- cmd.call(:name => a["name"])
22
- puts "" unless simple_output?
23
- end || err("No applications to act on.")
24
- else
25
- cmd.call
26
- end
27
- end
28
- end
8
+ option :manifest, :aliases => "-m", :value => :file,
9
+ :desc => "Path to manifest file to use"
29
10
 
30
- # same as above but in reverse dependency-order
31
- around(:stop) do |cmd, args|
32
- if args.empty? && !passed_value(:name)
33
- reversed = []
34
- each_app do |a|
35
- reversed.unshift a["name"]
36
- end || err("No applications to act on.")
37
11
 
38
- reversed.each do |name|
39
- cmd.call(:name => name)
40
- puts "" unless simple_output?
41
- end
42
- else
43
- cmd.call
44
- end
12
+ def no_apps
13
+ err "No applications or manifest to operate on."
45
14
  end
46
15
 
47
- around(:delete) do |cmd, args|
48
- if args.empty? && !options[:all] && !passed_value(:name)
49
- reversed = []
50
- has_manifest =
51
- each_app do |a|
52
- reversed.unshift a["name"]
53
- end
54
16
 
55
- if has_manifest
56
- reversed.each do |name|
57
- cmd.call(:name => name)
58
- puts "" unless simple_output?
17
+ # basic commands that, when given no name, act on the
18
+ # app(s) described by the manifest, in dependency-order
19
+ [ :start, :instances, :logs, :file, :files, :env,
20
+ :health, :stats, :scale
21
+ ].each do |wrap|
22
+ change_argument(wrap, :name, :optional)
23
+
24
+ around(wrap) do |cmd, input|
25
+ use_manifest =
26
+ specific_apps_or_all(input) do |app|
27
+ cmd.call(input.merge(:name => app[:name]))
28
+ puts "" unless quiet?
59
29
  end
60
- else
61
- cmd.call
30
+
31
+ # array of unhandled names
32
+ if use_manifest === Array
33
+ cmd.call(input.merge(:names => use_manifest))
34
+
35
+ # no manifest or no apps described by it
36
+ elsif !use_manifest
37
+ no_apps
62
38
  end
63
- else
64
- cmd.call
65
39
  end
66
40
  end
67
41
 
68
- # stop apps in reverse dependency order,
69
- # and then start in dependency order
70
- around(:restart) do |cmd, args|
71
- if args.empty? && !passed_value(:name)
42
+
43
+ # same as above but in reverse dependency-order
44
+ [:stop, :delete].each do |wrap|
45
+ around(wrap) do |cmd, input|
46
+ next cmd.call if input[:all]
47
+
72
48
  reversed = []
73
- forwards = []
74
- each_app do |a|
75
- reversed.unshift a["name"]
76
- forwards << a["name"]
77
- end || err("No applications to act on.")
78
-
79
- reversed.each do |name|
80
- with_inputs(:name => name) do
81
- stop
49
+ use_manifest =
50
+ specific_apps_or_all(input) do |app|
51
+ reversed.unshift app[:name]
82
52
  end
83
- end
84
53
 
85
- puts "" unless simple_output?
54
+ # array of unhandled names
55
+ if use_manifest === Array
56
+ cmd.call(input.merge(:names => use_manifest))
86
57
 
87
- forwards.each do |name|
88
- with_inputs(:name => name) do
89
- start
90
- end
58
+ # no manifest or no apps described by it
59
+ elsif !use_manifest
60
+ next no_apps
91
61
  end
92
- else
93
- cmd.call
62
+
63
+ cmd.call(input.merge(:names => reversed))
94
64
  end
95
65
  end
96
66
 
67
+
97
68
  # push and sync meta changes in the manifest
98
69
  # also sets env data on creation if present in manifest
99
- around(:push) do |push, args|
100
- name = passed_value(:name) || args.first
101
-
102
- use_name =
103
- if manifest && apps = manifest["applications"]
104
- apps.size == 1
105
- else
106
- # legacy single-app manifest
107
- true
108
- end
109
-
110
- all_pushed =
111
- each_app do |info|
112
- next if !use_name && name && info["name"] != name
113
-
114
- app_name = use_name ? name : info["name"]
115
-
116
- app = client.app(app_name)
117
-
118
- sync_changes(info)
119
-
120
- with_filters(:push_app => proc { |a| setup_app(a, info); a }) do
70
+ change_argument(:push, :name, :optional)
71
+ around(:push) do |push, input|
72
+ use_manifest =
73
+ specific_apps_or_all(input, true) do |app|
74
+ sync_changes(app)
75
+
76
+ with_filters(
77
+ :push => {
78
+ :push_app =>
79
+ proc { |a| setup_app(a, app); a }
80
+ }) do
121
81
  push.call(
122
- :name => app_name,
123
- :bind_services => false,
124
- :create_services => false)
82
+ input.merge(app).merge(
83
+ :bind_services => false,
84
+ :create_services => false))
125
85
  end
126
-
127
- puts "" unless simple_output?
128
86
  end
129
87
 
130
- unless all_pushed
88
+ unless use_manifest
131
89
  bound = []
132
90
 
133
- with_filters(:push_app => proc { |a| ask_to_save(a); a}) do
91
+ with_filters(
92
+ :push => {
93
+ :push_app =>
94
+ proc { |a| ask_to_save(input, a); a }
95
+ }) do
134
96
  push.call
135
97
  end
136
98
  end
137
99
  end
138
-
139
- # need to do this specially so it doesn't call it with the instance/memory
140
- # flags set (via each_app), which would cause it to do nothing
141
- around(:scale) do |cmd, args|
142
- if args.empty? && !passed_value(:name)
143
- apps = []
144
- has_manifest =
145
- each_app do |a|
146
- apps << a["name"]
147
- end
148
-
149
- if has_manifest
150
- apps.each do |name|
151
- cmd.call(:name => name)
152
- puts "" unless simple_output?
153
- end
154
- else
155
- cmd.call
156
- end
157
- else
158
- cmd.call
159
- end
160
- end
161
100
  end
@@ -1,3 +1,3 @@
1
1
  module VMCManifests
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -22,7 +22,7 @@ module VMCManifests
22
22
 
23
23
  # find the manifest file to work with
24
24
  def manifest_file
25
- return options[:manifest] if options[:manifest]
25
+ return option(:manifest) if option(:manifest)
26
26
  return @manifest_file if @manifest_file
27
27
 
28
28
  where = Dir.pwd
@@ -188,60 +188,58 @@ module VMCManifests
188
188
  end
189
189
  end
190
190
 
191
- def app_info(find_path)
192
- return unless manifest and manifest["applications"]
193
-
194
- manifest["applications"].each do |path, info|
195
- if info["framework"].is_a?(Hash)
196
- info["framework"] = info["framework"]["name"]
191
+ def app_info(find_path, input = nil)
192
+ return unless manifest
193
+
194
+ mandir = File.dirname(manifest_file)
195
+ full_path = File.expand_path(find_path, mandir)
196
+
197
+ path, info =
198
+ if apps = manifest["applications"]
199
+ manifest["applications"].find do |path, info|
200
+ if info["framework"].is_a?(Hash)
201
+ info["framework"] = info["framework"]["name"]
202
+ end
203
+
204
+ app = File.expand_path(path, mandir)
205
+ File.expand_path(path, mandir) == full_path
206
+ end
207
+ elsif find_path == "."
208
+ [".", {}]
197
209
  end
198
210
 
199
- app = File.expand_path(path, File.dirname(manifest_file))
200
- if find_path == app
201
- return toplevel_attributes.merge info
211
+ return unless info
212
+
213
+ data = { :path => full_path }
214
+
215
+ toplevel_attributes.merge(info).each do |k, v|
216
+ name = k.to_sym
217
+
218
+ if name == :mem
219
+ name = :memory
202
220
  end
221
+
222
+ data[name] = input && input.given(name) || v
203
223
  end
204
224
 
205
- nil
225
+ data
206
226
  end
207
227
 
208
228
  # call a block for each app in a manifest (in dependency order), setting
209
229
  # inputs for each app
210
- def each_app
211
- given_path = passed_value(:path)
212
- full_path = given_path && File.expand_path(given_path)
213
-
230
+ def each_app(input = nil, &blk)
214
231
  if manifest and all_apps = manifest["applications"]
215
232
  use_inputs = all_apps.size == 1
216
233
 
217
- # given a specific application
218
- if given_path
219
- if info = app_info(full_path)
220
- with_app(full_path, info, use_inputs) do
221
- yield info
222
- end
223
- else
224
- raise "Path #{given_path} is not described by the manifest."
225
- end
226
- else
227
- # all apps in the manifest
228
- ordered_by_deps(all_apps).each do |path|
229
- app = File.expand_path(path, File.dirname(manifest_file))
230
- info = app_info(app)
231
-
232
- with_app(app, info, use_inputs) do
233
- yield info
234
- end
235
- end
234
+ ordered_by_deps(all_apps).each do |path|
235
+ yield app_info(path, use_inputs && input)
236
236
  end
237
237
 
238
238
  true
239
-
239
+
240
240
  # manually created or legacy single-app manifest
241
241
  elsif single = toplevel_attributes
242
- with_app(full_path || ".", single, true) do
243
- yield single
244
- end
242
+ yield app_info(".", input)
245
243
 
246
244
  true
247
245
 
@@ -250,24 +248,56 @@ module VMCManifests
250
248
  end
251
249
  end
252
250
 
253
- private
251
+ # like each_app, but only acts on apps specified as paths instead of names
252
+ #
253
+ # returns the names that were not paths
254
+ def specific_apps_or_all(input = nil, use_name = true, &blk)
255
+ return false unless manifest && apps = manifest["applications"]
254
256
 
255
- # call the block as if the app info and path were given as flags
256
- def with_app(path, info, use_inputs = false, &blk)
257
- inputs = {:path => path}
258
- info.each do |k, v|
259
- input = k.to_sym
257
+ use_name = false if apps.size > 1
260
258
 
261
- if input == :mem
262
- input = :memory
259
+ names_or_paths =
260
+ if input.given?(:names)
261
+ input[:names]
262
+ elsif input.given?(:name)
263
+ [input[:name]]
264
+ else
265
+ []
263
266
  end
264
267
 
265
- inputs[input] = use_inputs && passed_value(input) || v
268
+ return each_app(input, &blk) if names_or_paths.empty?
269
+
270
+ input = input.without(:name, :names)
271
+
272
+ paths = []
273
+ names = []
274
+ names_or_paths.each do |x|
275
+ path = File.expand_path(x)
276
+
277
+ if File.exists?(path)
278
+ paths << path
279
+ else
280
+ names << x
281
+ end
266
282
  end
267
283
 
268
- with_inputs(inputs, &blk)
284
+ paths.each do |path|
285
+ blk.call app_info(path, input)
286
+ end
287
+
288
+ if use_name && names.size == 1
289
+ blk.call(
290
+ app_info(
291
+ manifest["applications"].keys.first,
292
+ input.merge(:name => names.first)))
293
+ end
294
+
295
+ names
269
296
  end
270
297
 
298
+
299
+ private
300
+
271
301
  # sort applications in dependency order
272
302
  # e.g. if A depends on B, B will be listed before A
273
303
  def ordered_by_deps(apps, abspaths = nil, processed = Set[])
@@ -313,18 +343,18 @@ module VMCManifests
313
343
  # redeploys the app if necessary (after prompting the user), e.g. for
314
344
  # runtime/framework change
315
345
  def sync_changes(info)
316
- app = client.app(info["name"])
346
+ app = client.app(info[:name])
317
347
  return unless app.exists?
318
348
 
319
349
  diff = {}
320
350
  need_restage = []
321
351
  info.each do |k, v|
322
- case k
352
+ case k.to_s
323
353
  when /ur[li]s?/
324
354
  old = app.urls
325
355
  new = Array(v)
326
356
  if old != new
327
- diff["urls"] = [old.inspect, new.inspect]
357
+ diff[:urls] = [old.inspect, new.inspect]
328
358
  app.urls = new
329
359
  end
330
360
  when "env"
@@ -351,7 +381,7 @@ module VMCManifests
351
381
  new = megabytes(v)
352
382
 
353
383
  if old != new
354
- diff["memory"] = [human_size(old * 1024 * 1024, 0), v]
384
+ diff[:memory] = [human_size(old * 1024 * 1024, 0), v]
355
385
  app.memory = new
356
386
  end
357
387
  end
@@ -359,7 +389,7 @@ module VMCManifests
359
389
 
360
390
  return if diff.empty?
361
391
 
362
- unless simple_output?
392
+ unless quiet?
363
393
  puts "Detected the following changes to #{c(app.name, :name)}:"
364
394
  diff.each do |k, d|
365
395
  old, new = d
@@ -375,7 +405,7 @@ module VMCManifests
375
405
  app.update!
376
406
  end
377
407
  else
378
- unless simple_output?
408
+ unless quiet?
379
409
  puts "The following changes require the app to be recreated:"
380
410
  need_restage.each do |n|
381
411
  puts " #{c(n, :error)}"
@@ -395,7 +425,7 @@ module VMCManifests
395
425
  end
396
426
  end
397
427
 
398
- def ask_to_save(app)
428
+ def ask_to_save(input, app)
399
429
  return if manifest_file
400
430
 
401
431
  services = app.services.collect { |name| client.service(name) }
@@ -427,7 +457,7 @@ module VMCManifests
427
457
  if ask("Save configuration?", :default => false)
428
458
  File.open("manifest.yml", "w") do |io|
429
459
  YAML.dump(
430
- {"applications" => {(options[:path] || ".") => meta}},
460
+ {"applications" => {(input[:path] || ".") => meta}},
431
461
  io)
432
462
  end
433
463
 
@@ -436,13 +466,13 @@ module VMCManifests
436
466
  end
437
467
 
438
468
  def setup_app(app, info)
439
- app.env = info["env"]
469
+ app.env = info[:env]
440
470
 
441
- return if !info["services"] || info["services"].empty?
471
+ return if !info[:services] || info[:services].empty?
442
472
 
443
473
  services = client.system_services
444
474
 
445
- info["services"].each do |name, svc|
475
+ info[:services].each do |name, svc|
446
476
  service = client.service(name)
447
477
 
448
478
  unless service.exists?
@@ -460,6 +490,6 @@ module VMCManifests
460
490
  end
461
491
  end
462
492
 
463
- app.services = info["services"].keys
493
+ app.services = info[:services].keys
464
494
  end
465
495
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manifests-vmc-plugin
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 4
10
- version: 0.2.4
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Suraci
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-06-22 00:00:00 Z
18
+ date: 2012-07-03 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description: