tools-cf-plugin 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -44,9 +44,6 @@ module CFTools::Tunnel
44
44
  tunnel_to(nats["address"], nats["port"], gateway)
45
45
  end
46
46
 
47
- line "port: #{nport}"
48
- line "creds: #{nats}"
49
-
50
47
  with_progress("Logging in as admin user") do
51
48
  login_as_admin(manifest)
52
49
  end
@@ -1,3 +1,3 @@
1
1
  module CFTools
2
- VERSION = "2.1.1".freeze
2
+ VERSION = "2.2.0".freeze
3
3
  end
@@ -3,17 +3,18 @@ require "nats/client"
3
3
 
4
4
  module CFTools
5
5
  class Watch < CF::App::Base
6
- def precondition
7
- check_target
8
- end
6
+ def precondition; end
9
7
 
10
8
  REPLY_PREFIX = "`- reply to "
11
9
  COLUMN_WIDTH = 30
12
10
 
13
11
  desc "Watch messages going over NATS relevant to an application"
14
12
  group :admin
15
- input :app, :argument => :optional, :from_given => by_name(:app),
13
+ input :app, :argument => :optional, :from_given => by_name(:apps),
16
14
  :desc => "Application to watch"
15
+ input :subjects, :aliases => %w[-s --subject],
16
+ :from_given => proc { |s| s.split(",") },
17
+ :desc => "NATS subject to subscribe to"
17
18
  input :host, :alias => "-h", :default => "127.0.0.1",
18
19
  :desc => "NATS server address"
19
20
  input :port, :alias => "-P", :default => 4222, :type => :integer,
@@ -23,11 +24,12 @@ module CFTools
23
24
  input :password, :alias => "-p", :default => "nats",
24
25
  :desc => "NATS server password"
25
26
  def watch
26
- app = input[:app]
27
+ app = get_app(input[:app])
27
28
  host = input[:host]
28
29
  port = input[:port]
29
30
  user = input[:user]
30
31
  pass = input[:password]
32
+ subjects = input[:subjects] || [">"]
31
33
 
32
34
  @requests = {}
33
35
  @seen_apps = {}
@@ -35,7 +37,7 @@ module CFTools
35
37
 
36
38
  $stdout.sync = true
37
39
 
38
- watching_nats("nats://#{user}:#{pass}@#{host}:#{port}") do |msg, reply, sub|
40
+ watching_nats("nats://#{user}:#{pass}@#{host}:#{port}", subjects) do |msg, reply, sub|
39
41
  begin
40
42
  if @requests.include?(sub)
41
43
  process_response(sub, reply, msg, app)
@@ -65,7 +67,7 @@ module CFTools
65
67
  def process_message(sub, reply, msg, app)
66
68
  register_request(sub, reply) if reply
67
69
 
68
- payload = JSON.parse(msg) # rescue msg
70
+ payload = JSON.parse(msg) rescue msg
69
71
 
70
72
  case sub
71
73
  when "dea.advertise"
@@ -81,7 +83,6 @@ module CFTools
81
83
  when "router.start"
82
84
  sub, payload = pretty_router_start(sub, payload)
83
85
  when "router.register"
84
- return if !app && payload.has_key?("dea")
85
86
  sub, payload = pretty_register(sub, payload)
86
87
  when "router.unregister"
87
88
  sub, payload = pretty_unregister(sub, payload)
@@ -101,8 +102,10 @@ module CFTools
101
102
  sub, payload = pretty_healthmanager_health(sub, payload)
102
103
  when "dea.shutdown"
103
104
  sub, payload = pretty_dea_shutdown(sub, payload)
104
- when /^cloudcontrollers\.hm\.requests\.\w+$/
105
- sub, payload = process_cloudcontrollers_hm_request(payload)
105
+ when "health.start"
106
+ sub, payload = pretty_health_start(sub, payload)
107
+ when "health.stop"
108
+ sub, payload = pretty_health_stop(sub, payload)
106
109
  when /^([^.]+)\.announce$/
107
110
  sub, payload = pretty_service_announcement(sub, payload)
108
111
  when "vcap.component.announce"
@@ -168,13 +171,13 @@ module CFTools
168
171
  [ c(sub, :bad),
169
172
  [ "app: #{pretty_app(payload["droplet"])}",
170
173
  "reason: #{payload["reason"]}",
171
- "index: #{payload["index"]}"
174
+ "index: #{payload["index"]}",
175
+ "version: #{pretty_version(payload["version"])}"
172
176
  ].join(", ")
173
177
  ]
174
178
  end
175
179
 
176
180
  def pretty_heartbeat(sub, payload, app)
177
-
178
181
  dea, _ = payload["dea"].split("-", 2)
179
182
 
180
183
  states = Hash.new(0)
@@ -233,7 +236,8 @@ module CFTools
233
236
  [ "app: #{pretty_app(payload["droplet"])}",
234
237
  "dea: #{dea}",
235
238
  "index: #{payload["index"]}",
236
- "uris: #{list(payload["uris"])}"
239
+ "version: #{pretty_version(payload["version"])}",
240
+ "uris: #{list(Array(payload["uris"]))}"
237
241
  ].join(", ")
238
242
  ]
239
243
  end
@@ -241,6 +245,10 @@ module CFTools
241
245
  def pretty_stop(sub, payload)
242
246
  message = ["app: #{pretty_app(payload["droplet"])}"]
243
247
 
248
+ if (version = payload["version"])
249
+ message << "version: #{pretty_version(version)}"
250
+ end
251
+
244
252
  if (indices = payload["indices"])
245
253
  message << "scaling down indices: #{indices.join(", ")}"
246
254
  elsif (instances = payload["instances"])
@@ -261,10 +269,14 @@ module CFTools
261
269
  end
262
270
 
263
271
  def pretty_find_droplet(sub, payload)
264
- states = payload["states"].collect { |s| c(s.downcase, state_color(s))}
272
+ states = (payload["states"] || []).collect do |s|
273
+ c(s.downcase, state_color(s))
274
+ end
275
+
265
276
  [ d(sub),
266
277
  [ "app: #{pretty_app(payload["droplet"])}",
267
- "querying states: #{states.join(", ")}"
278
+ "version: #{pretty_version(payload["version"])}",
279
+ "querying states: #{list(states)}"
268
280
  ].join(", ")
269
281
  ]
270
282
  end
@@ -273,20 +285,25 @@ module CFTools
273
285
  dea, _ = payload["dea"].split("-", 2)
274
286
  index = payload["index"]
275
287
  state = payload["state"]
276
- time = Time.at(payload["state_timestamp"])
288
+ version = payload["version"]
289
+ since = Time.at(payload["state_timestamp"])
277
290
  [ sub,
278
291
  [ "dea: #{dea}",
279
292
  "index: #{index}",
280
293
  "state: #{c(state.downcase, state_color(state))}",
281
- "since: #{time}"
294
+ "version: #{pretty_version(version)}",
295
+ "since: #{since}"
282
296
  ].join(", ")
283
297
  ]
284
298
  end
285
299
 
286
300
  def pretty_healthmanager_status(sub, payload)
287
301
  state = payload["state"]
302
+ version = payload["version"]
303
+
288
304
  [ d(sub),
289
305
  [ "app: #{pretty_app(payload["droplet"])}",
306
+ "version: #{pretty_version(version)}",
290
307
  "querying states: #{c(state.downcase, state_color(state))}"
291
308
  ].join(", ")
292
309
  ]
@@ -297,13 +314,17 @@ module CFTools
297
314
  end
298
315
 
299
316
  def pretty_healthmanager_health(sub, payload)
300
- apps = payload["droplets"].collect { |d| pretty_app(d["droplet"]) }
317
+ apps = payload["droplets"].collect do |d|
318
+ "#{pretty_app(d["droplet"])} (#{pretty_version(d["version"])})"
319
+ end
320
+
301
321
  [d(sub), "querying health for: #{list(apps)}"]
302
322
  end
303
323
 
304
324
  def pretty_healthmanager_health_response(sub, payload)
305
325
  [ sub,
306
326
  [ "app: #{pretty_app(payload["droplet"])}",
327
+ "version: #{pretty_version(payload["version"])}",
307
328
  "healthy: #{payload["healthy"]}"
308
329
  ].join(", ")
309
330
  ]
@@ -323,25 +344,23 @@ module CFTools
323
344
  [c(sub, :error), "dea: #{dea}, apps: #{list(apps)}"]
324
345
  end
325
346
 
326
- def process_cloudcontrollers_hm_request(payload)
327
- last_updated = Time.at(payload["last_updated"])
328
-
329
- op = payload["op"]
330
-
331
- message = [
332
- "app: #{pretty_app(payload["droplet"])}",
333
- "operation: #{pretty_hm_op(op)}",
334
- "app last updated: #{last_updated}"
347
+ def pretty_health_start(sub, payload)
348
+ [ c(sub, :good),
349
+ [ "app: #{pretty_app(payload["droplet"])}",
350
+ "version: #{pretty_version(payload["version"])}",
351
+ "indices: #{list(payload["indices"])}",
352
+ "running: #{pretty_running_counts(payload["running"])}"
353
+ ].join(", ")
335
354
  ]
355
+ end
336
356
 
337
- case op
338
- when "STOP"
339
- message << "instances: #{list(payload["instances"])}"
340
- when "START"
341
- message << "indices: #{list(payload["indices"])}"
342
- end
343
-
344
- [c("hm.request", :warning), message.join(", ")]
357
+ def pretty_health_stop(sub, payload)
358
+ [ c(sub, :bad),
359
+ [ "app: #{pretty_app(payload["droplet"])}",
360
+ "instances: #{pretty_instance_breakdown(payload["instances"])}",
361
+ "running: #{pretty_running_counts(payload["running"])}"
362
+ ].join(", ")
363
+ ]
345
364
  end
346
365
 
347
366
  def pretty_service_announcement(sub, payload)
@@ -398,18 +417,25 @@ module CFTools
398
417
  [d(sub), message.join(", ")]
399
418
  end
400
419
 
401
- def pretty_hm_op(op)
402
- case op
403
- when "STOP"
404
- c("stop", :bad)
405
- when "START"
406
- c("start", :good)
407
- else
408
- op
409
- end
420
+ def pretty_running_counts(running)
421
+ running.collect do |ver, num|
422
+ "#{num} x #{pretty_version(ver)}"
423
+ end.join(", ")
424
+ end
425
+
426
+ def pretty_instance_breakdown(instances)
427
+ instances.collect do |inst, ver|
428
+ "#{inst} (#{pretty_version(ver)})"
429
+ end.join(", ")
430
+ end
431
+
432
+ def pretty_version(guid)
433
+ guid.split("-").first
410
434
  end
411
435
 
412
436
  def pretty_app(guid)
437
+ return guid unless client
438
+
413
439
  existing_app =
414
440
  if @seen_apps.key?(guid)
415
441
  @seen_apps[guid]
@@ -419,22 +445,45 @@ module CFTools
419
445
  end
420
446
 
421
447
  if existing_app
422
- #@seen_apps[guid] = existing_app
448
+ @seen_apps[guid] = existing_app
423
449
  c(existing_app.name, :name)
424
450
  else
425
451
  @seen_apps[guid] = nil
426
452
  d("unknown (#{guid})")
427
453
  end
454
+ rescue CFoundry::TargetRefused, CFoundry::InvalidAuthToken
455
+ guid
428
456
  end
429
457
 
430
- def watching_nats(uri, &blk)
458
+ def watching_nats(uri, subjects, &blk)
431
459
  NATS.start(:uri => uri) do
432
- NATS.subscribe(">", &blk)
460
+ subjects.each do |subject|
461
+ NATS.subscribe(subject, &blk)
462
+ end
433
463
  end
434
464
  end
435
465
 
436
466
  def register_request(sub, reply)
437
467
  @requests[reply] = [sub, @request_ticker += 1]
438
468
  end
469
+
470
+ def get_app(apps)
471
+ return unless apps
472
+
473
+ if apps.empty?
474
+ fail "Unknown app '#{input.given[:app]}'."
475
+ elsif apps.size == 1
476
+ apps.first
477
+ else
478
+ disambiguate_app(apps)
479
+ end
480
+ end
481
+
482
+ def disambiguate_app(apps)
483
+ ask("Which application?", :choices => apps,
484
+ :display => proc do |a|
485
+ "#{a.name} (#{a.space.organization.name}/#{a.space.name})"
486
+ end)
487
+ end
439
488
  end
440
489
  end
@@ -33,6 +33,21 @@ describe CFTools::Watch do
33
33
  cf %W[watch]
34
34
  end
35
35
 
36
+ context "when a subject is given" do
37
+ it "subscribes to the given subject on NATS" do
38
+ expect(NATS).to receive(:subscribe).with("some.subject")
39
+ cf %W[watch --subject some.subject]
40
+ end
41
+
42
+ context "when multiple subjects are given" do
43
+ it "subscribes to all of them on NATS" do
44
+ expect(NATS).to receive(:subscribe).with("some.subject")
45
+ expect(NATS).to receive(:subscribe).with("some.other.subject")
46
+ cf %W[watch --subjects some.subject,some.other.subject]
47
+ end
48
+ end
49
+ end
50
+
36
51
  context "when no application is given" do
37
52
  around { |example| Timecop.freeze(&example) }
38
53
 
@@ -104,6 +119,25 @@ describe CFTools::Watch do
104
119
  end
105
120
  end
106
121
 
122
+ context "and multiple apps with the sane name are found" do
123
+ let!(:org1) { fake :organization, :name => "org1" }
124
+ let!(:org2) { fake :organization, :name => "org2" }
125
+ let!(:space1) { fake :space, :name => "space1", :organization => org1 }
126
+ let!(:space2) { fake :space, :name => "space2", :organization => org2 }
127
+ let!(:app1) { fake :app, :name => "myapp", :guid => "myappguid", :space => space1 }
128
+ let!(:app2) { fake :app, :name => "myapp", :guid => "myappguid", :space => space2 }
129
+
130
+ let(:client) { fake_client :apps => [app1, app2] }
131
+
132
+ it "asks to disambiguate" do
133
+ should_ask("Which application?", hash_including(:choices => [app1, app2])) do |_, opts|
134
+ expect(opts[:display].call(app1)).to eq("myapp (org1/space1)")
135
+ end
136
+
137
+ cf %W[watch myapp]
138
+ end
139
+ end
140
+
107
141
  context "and a message containing the app's GUID is seen" do
108
142
  around { |example| Timecop.freeze(&example) }
109
143
 
@@ -146,7 +180,7 @@ PAYLOAD
146
180
  it "pretty-prints the message body" do
147
181
  cf %W[watch]
148
182
 
149
- expect(output).to say("app: myapp, reason: STOPPED, index: 0")
183
+ expect(output).to say("app: myapp, reason: STOPPED, index: 0, version: aaca113b")
150
184
  end
151
185
  end
152
186
 
@@ -172,7 +206,7 @@ PAYLOAD
172
206
  "state": "CRASHED",
173
207
  "index": 1,
174
208
  "instance": "some other app instance",
175
- "version": "5c0e0e10-8384-4a35-915e-872fe91ffb95",
209
+ "version": "deadbeef-8384-4a35-915e-872fe91ffb95",
176
210
  "droplet": "#{app.guid}",
177
211
  "cc_partition": "default"
178
212
  },
@@ -453,10 +487,42 @@ PAYLOAD
453
487
  expect(output).to say("dea.42.start")
454
488
  end
455
489
 
456
- it "prints the uris, host, and port" do
490
+ it "prints the app, dea, index, version, and uris" do
457
491
  cf %W[watch]
458
492
 
459
- expect(output).to say("app: myapp, dea: 42, index: 2, uris: myapp.com")
493
+ expect(output).to say("app: myapp, dea: 42, index: 2, version: ce1da6af, uris: myapp.com")
494
+ end
495
+
496
+ context "when a single uri is given as a string" do
497
+ let(:payload) { <<PAYLOAD }
498
+ {
499
+ "index": 2,
500
+ "debug": null,
501
+ "console": true,
502
+ "env": [],
503
+ "cc_partition": "default",
504
+ "limits": {
505
+ "fds": 16384,
506
+ "disk": 1024,
507
+ "mem": 128
508
+ },
509
+ "services": [],
510
+ "droplet": "#{app.guid}",
511
+ "name": "hello-sinatra",
512
+ "uris": "myapp.com",
513
+ "prod": false,
514
+ "sha1": "9c8f36ee81b535a7d9b4efcd9d629e8cf8a2645f",
515
+ "executableFile": "deprecated",
516
+ "executableUri": "https://a1-cf-app-com-cc-droplets.s3.amazonaws.com/ac/cf/accf1078-e7e1-439a-bd32-77296390c406?AWSAccessKeyId=AKIAIMGCF7E5F6M5RV3A&Signature=1lyIotK3cZ2VUyK3H8YrlT82B8c%3D&Expires=1369259081",
517
+ "version": "ce1da6af-59b1-4fea-9e39-64c19440a671"
518
+ }
519
+ PAYLOAD
520
+
521
+ it "prints the app, dea, index, version, and uris" do
522
+ cf %W[watch]
523
+
524
+ expect(output).to say("app: myapp, dea: 42, index: 2, version: ce1da6af, uris: myapp.com")
525
+ end
460
526
  end
461
527
  end
462
528
 
@@ -497,7 +563,7 @@ PAYLOAD
497
563
  it "prints that it's scaling down, and the affected indices" do
498
564
  cf %W[watch]
499
565
 
500
- expect(output).to say("app: myapp, scaling down indices: 1, 2")
566
+ expect(output).to say("app: myapp, version: ce1da6af, scaling down indices: 1, 2")
501
567
  end
502
568
  end
503
569
 
@@ -568,6 +634,8 @@ PAYLOAD
568
634
  }
569
635
  PAYLOAD
570
636
 
637
+ let(:state_timestamp) { "1369262704.3337305" }
638
+
571
639
  let(:response_payload) { <<PAYLOAD }
572
640
  {
573
641
  "console_port": 61016,
@@ -579,11 +647,11 @@ PAYLOAD
579
647
  ],
580
648
  "dea": "1-c0d2928b36c524153cdc8cfb51d80f75",
581
649
  "droplet": "#{app.guid}",
582
- "version": "c75b3e45-0cf4-403d-a54d-1c0970dca50d",
650
+ "version": "878318bf-0cf4-403d-a54d-1c0970dca50d",
583
651
  "instance": "7cc4f4fe64c7a0fbfaacf71e9e222a35",
584
652
  "index": 0,
585
653
  "state": "RUNNING",
586
- "state_timestamp": 1369262704.3337305,
654
+ "state_timestamp": #{state_timestamp},
587
655
  "file_uri": "http://10.10.17.1:12345/instances"
588
656
  }
589
657
  PAYLOAD
@@ -591,7 +659,22 @@ PAYLOAD
591
659
  it "prints the states being queried" do
592
660
  cf %W[watch]
593
661
 
594
- expect(output).to say("app: myapp, querying states: starting, running")
662
+ expect(output).to say("app: myapp, version: 878318bf, querying states: starting, running")
663
+ end
664
+
665
+ context "when there are no states being queried" do
666
+ let(:payload) { <<PAYLOAD }
667
+ {
668
+ "version": "878318bf-64a0-4055-b79b-46871292ceb8",
669
+ "droplet": "#{app.guid}"
670
+ }
671
+ PAYLOAD
672
+
673
+ it "prints them as 'none'" do
674
+ cf %W[watch]
675
+
676
+ expect(output).to say("app: myapp, version: 878318bf, querying states: none")
677
+ end
595
678
  end
596
679
 
597
680
  context "and we see the response" do
@@ -604,7 +687,7 @@ PAYLOAD
604
687
  it "pretty-prints the response" do
605
688
  cf %W[watch]
606
689
 
607
- expect(output).to say("reply to dea.find.droplet (1)\tdea: 1, index: 0, state: running, since: 2013-05-22 15:45:04 -0700")
690
+ expect(output).to say("reply to dea.find.droplet (1)\tdea: 1, index: 0, state: running, version: 878318bf, since: #{Time.at(state_timestamp.to_f)}")
608
691
  end
609
692
  end
610
693
  end
@@ -632,7 +715,7 @@ PAYLOAD
632
715
  it "prints the states being queried" do
633
716
  cf %W[watch]
634
717
 
635
- expect(output).to say("app: myapp, querying states: flapping")
718
+ expect(output).to say("app: myapp, version: 50512eed, querying states: flapping")
636
719
  end
637
720
 
638
721
  context "and we see the response" do
@@ -661,11 +744,11 @@ PAYLOAD
661
744
  {
662
745
  "droplets": [
663
746
  {
664
- "version": "some-version",
747
+ "version": "deadbeef-foo",
665
748
  "droplet": "#{app.guid}"
666
749
  },
667
750
  {
668
- "version": "some-other-version",
751
+ "version": "beefdead-foo",
669
752
  "droplet": "#{other_app.guid}"
670
753
  }
671
754
  ]
@@ -675,7 +758,7 @@ PAYLOAD
675
758
  let(:response_payload) { <<PAYLOAD }
676
759
  {
677
760
  "healthy": 2,
678
- "version": "some-version",
761
+ "version": "deadbeef-foo",
679
762
  "droplet": "#{app.guid}"
680
763
  }
681
764
  PAYLOAD
@@ -683,7 +766,7 @@ PAYLOAD
683
766
  let(:other_response_payload) { <<PAYLOAD }
684
767
  {
685
768
  "healthy": 3,
686
- "version": "some-version",
769
+ "version": "beefdead-foo",
687
770
  "droplet": "#{other_app.guid}"
688
771
  }
689
772
  PAYLOAD
@@ -693,7 +776,7 @@ PAYLOAD
693
776
  it "prints the apps whose health being queried" do
694
777
  cf %W[watch]
695
778
 
696
- expect(output).to say("querying health for: myapp, otherapp")
779
+ expect(output).to say("querying health for: myapp (deadbeef), otherapp (beefdead)")
697
780
  end
698
781
 
699
782
  context "and we see the response" do
@@ -707,8 +790,8 @@ PAYLOAD
707
790
  it "pretty-prints the response" do
708
791
  cf %W[watch]
709
792
 
710
- expect(output).to say("reply to healthmanager.health (1)\tapp: myapp, healthy: 2")
711
- expect(output).to say("reply to healthmanager.health (1)\tapp: otherapp, healthy: 3")
793
+ expect(output).to say("reply to healthmanager.health (1)\tapp: myapp, version: deadbeef, healthy: 2")
794
+ expect(output).to say("reply to healthmanager.health (1)\tapp: otherapp, version: beefdead, healthy: 3")
712
795
  end
713
796
  end
714
797
  end
@@ -760,58 +843,60 @@ PAYLOAD
760
843
  end
761
844
  end
762
845
 
763
- context "when a message is seen with subject cloudcontrollers.hm.requests.*" do
764
- let(:subject) { "cloudcontrollers.hm.requests.default" }
846
+ context "when a message is seen with subject health.start" do
847
+ let(:subject) { "health.start" }
765
848
 
766
849
  let(:last_updated) { Time.now }
767
850
 
768
- context "and it is a STOP operation" do
769
- let(:payload) { <<PAYLOAD }
851
+ let(:payload) { <<PAYLOAD }
770
852
  {
771
- "instances": [
772
- "some-instance",
773
- "some-other-instance"
853
+ "indices": [
854
+ 1,
855
+ 3
774
856
  ],
857
+ "running": {
858
+ "deadbeef-version": 1,
859
+ "beefdead-version": 2
860
+ },
861
+ "version": "deadbeef-foo",
775
862
  "last_updated": #{last_updated.to_i},
776
- "op": "STOP",
777
863
  "droplet": "#{app.guid}"
778
864
  }
779
865
  PAYLOAD
780
866
 
781
- it "trims the subject" do
782
- cf %W[watch]
867
+ it "prints the operation, last updated timestamp, and instances" do
868
+ cf %W[watch]
783
869
 
784
- expect(output).to say(/\s+hm\.request\s+/)
785
- end
870
+ expect(output).to say(
871
+ "app: myapp, version: deadbeef, indices: 1, 3, running: 1 x deadbeef, 2 x beefdead")
872
+ end
873
+ end
786
874
 
787
- it "prints the operation, last updated timestamp, and instances" do
788
- cf %W[watch]
875
+ context "when a message is seen with subject health.stop" do
876
+ let(:subject) { "health.stop" }
789
877
 
790
- expect(output).to say(
791
- "app: myapp, operation: stop, app last updated: #{last_updated}, instances: some-instance, some-other-instance")
792
- end
793
- end
878
+ let(:last_updated) { Time.now }
794
879
 
795
- context "and it is a START operation" do
796
- let(:payload) { <<PAYLOAD }
880
+ let(:payload) { <<PAYLOAD }
797
881
  {
798
- "indices": [
799
- 1,
800
- 3
801
- ],
802
- "version": "some-version",
882
+ "instances": {
883
+ "some-instance": "deadbeef-version",
884
+ "some-other-instance": "beefdead-version"
885
+ },
886
+ "running": {
887
+ "deadbeef-version": 1,
888
+ "beefdead-version": 2
889
+ },
803
890
  "last_updated": #{last_updated.to_i},
804
- "op": "START",
805
891
  "droplet": "#{app.guid}"
806
892
  }
807
893
  PAYLOAD
808
894
 
809
- it "prints the operation, last updated timestamp, and instances" do
810
- cf %W[watch]
895
+ it "prints the operation, last updated timestamp, and instances" do
896
+ cf %W[watch]
811
897
 
812
- expect(output).to say(
813
- "app: myapp, operation: start, app last updated: #{last_updated}, indices: 1, 3")
814
- end
898
+ expect(output).to say(
899
+ "app: myapp, instances: some-instance (deadbeef), some-other-instance (beefdead), running: 1 x deadbeef, 2 x beefdead")
815
900
  end
816
901
  end
817
902
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tools-cf-plugin
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-24 00:00:00.000000000 Z
12
+ date: 2013-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cfoundry
@@ -271,29 +271,29 @@ extensions: []
271
271
  extra_rdoc_files: []
272
272
  files:
273
273
  - Rakefile
274
- - lib/tools-cf-plugin/dea-ads.rb
275
- - lib/tools-cf-plugin/dea-apps.rb
276
274
  - lib/tools-cf-plugin/plugin.rb
277
- - lib/tools-cf-plugin/shell.rb
278
- - lib/tools-cf-plugin/tunnel/base.rb
275
+ - lib/tools-cf-plugin/version.rb
276
+ - lib/tools-cf-plugin/tunnel/watch-logs.rb
279
277
  - lib/tools-cf-plugin/tunnel/log_entry.rb
280
- - lib/tools-cf-plugin/tunnel/multi_line_stream.rb
281
- - lib/tools-cf-plugin/tunnel/stream_location.rb
282
278
  - lib/tools-cf-plugin/tunnel/tunnel-nats.rb
283
- - lib/tools-cf-plugin/tunnel/watch-logs.rb
284
- - lib/tools-cf-plugin/version.rb
279
+ - lib/tools-cf-plugin/tunnel/stream_location.rb
280
+ - lib/tools-cf-plugin/tunnel/base.rb
281
+ - lib/tools-cf-plugin/tunnel/multi_line_stream.rb
285
282
  - lib/tools-cf-plugin/watch.rb
286
- - spec/dea-ads_spec.rb
287
- - spec/dea-apps_spec.rb
283
+ - lib/tools-cf-plugin/dea-apps.rb
284
+ - lib/tools-cf-plugin/shell.rb
285
+ - lib/tools-cf-plugin/dea-ads.rb
288
286
  - spec/shell_spec.rb
287
+ - spec/watch_spec.rb
289
288
  - spec/spec_helper.rb
290
- - spec/tunnel/base_spec.rb
289
+ - spec/dea-apps_spec.rb
290
+ - spec/dea-ads_spec.rb
291
291
  - spec/tunnel/log_entry_spec.rb
292
- - spec/tunnel/multi_line_stream_spec.rb
292
+ - spec/tunnel/watch-logs_spec.rb
293
+ - spec/tunnel/base_spec.rb
293
294
  - spec/tunnel/stream_location_spec.rb
295
+ - spec/tunnel/multi_line_stream_spec.rb
294
296
  - spec/tunnel/tunnel-nats_spec.rb
295
- - spec/tunnel/watch-logs_spec.rb
296
- - spec/watch_spec.rb
297
297
  homepage: http://github.com/cloudfoundry/tools-cf-plugin
298
298
  licenses: []
299
299
  post_install_message:
@@ -319,15 +319,14 @@ signing_key:
319
319
  specification_version: 3
320
320
  summary: Cloud Foundry tooling commands.
321
321
  test_files:
322
- - spec/dea-ads_spec.rb
323
- - spec/dea-apps_spec.rb
324
322
  - spec/shell_spec.rb
323
+ - spec/watch_spec.rb
325
324
  - spec/spec_helper.rb
326
- - spec/tunnel/base_spec.rb
325
+ - spec/dea-apps_spec.rb
326
+ - spec/dea-ads_spec.rb
327
327
  - spec/tunnel/log_entry_spec.rb
328
- - spec/tunnel/multi_line_stream_spec.rb
328
+ - spec/tunnel/watch-logs_spec.rb
329
+ - spec/tunnel/base_spec.rb
329
330
  - spec/tunnel/stream_location_spec.rb
331
+ - spec/tunnel/multi_line_stream_spec.rb
330
332
  - spec/tunnel/tunnel-nats_spec.rb
331
- - spec/tunnel/watch-logs_spec.rb
332
- - spec/watch_spec.rb
333
- has_rdoc: