tools-cf-plugin 2.0.0 → 2.1.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.
- data/lib/tools-cf-plugin/dea-ads.rb +1 -1
- data/lib/tools-cf-plugin/tunnel/multi_line_stream.rb +10 -1
- data/lib/tools-cf-plugin/tunnel/tunnel-nats.rb +4 -0
- data/lib/tools-cf-plugin/tunnel/watch-logs.rb +10 -6
- data/lib/tools-cf-plugin/version.rb +1 -1
- data/lib/tools-cf-plugin/watch.rb +93 -28
- data/spec/dea-ads_spec.rb +29 -13
- data/spec/shell_spec.rb +3 -3
- data/spec/spec_helper.rb +0 -1
- data/spec/tunnel/base_spec.rb +39 -43
- data/spec/tunnel/multi_line_stream_spec.rb +31 -15
- data/spec/tunnel/stream_location_spec.rb +4 -7
- data/spec/tunnel/tunnel-nats_spec.rb +28 -31
- data/spec/tunnel/watch-logs_spec.rb +26 -24
- data/spec/watch_spec.rb +176 -235
- metadata +45 -39
@@ -2,12 +2,12 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
module CFTools::Tunnel
|
4
4
|
describe MultiLineStream do
|
5
|
-
let(:director) {
|
5
|
+
let(:director) { double }
|
6
6
|
let(:deployment) { "some-deployment" }
|
7
7
|
let(:gateway_user) { "vcap" }
|
8
8
|
let(:gateway_host) { "vcap.me" }
|
9
9
|
|
10
|
-
let(:gateway) {
|
10
|
+
let(:gateway) { double }
|
11
11
|
let(:entries) { Queue.new }
|
12
12
|
|
13
13
|
subject do
|
@@ -15,10 +15,10 @@ module CFTools::Tunnel
|
|
15
15
|
end
|
16
16
|
|
17
17
|
before do
|
18
|
-
stub(
|
19
|
-
stub(
|
20
|
-
stub(
|
21
|
-
stub(
|
18
|
+
subject.stub(:create_ssh_user => ["1.2.3.4", "some_user_1"])
|
19
|
+
subject.stub(:gateway => gateway)
|
20
|
+
subject.stub(:entry_queue => entries)
|
21
|
+
Thread.stub(:new).and_yield
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "#stream" do
|
@@ -36,14 +36,14 @@ module CFTools::Tunnel
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it "spawns a SSH tunnel for each location" do
|
39
|
-
|
40
|
-
|
39
|
+
expect(Thread).to receive(:new).ordered
|
40
|
+
expect(Thread).to receive(:new).ordered
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
expect(subject).to receive(:create_ssh_user).with("foo", 0, entries) { ["1.2.3.4", "some_user_1"] }
|
43
|
+
expect(subject).to receive(:create_ssh_user).with("bar", 0, entries) { ["1.2.3.5", "some_user_2"] }
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
expect(gateway).to receive(:ssh).with("1.2.3.4", "some_user_1")
|
46
|
+
expect(gateway).to receive(:ssh).with("1.2.3.5", "some_user_2")
|
47
47
|
|
48
48
|
entries << nil
|
49
49
|
|
@@ -51,7 +51,7 @@ module CFTools::Tunnel
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it "streams from each location" do
|
54
|
-
ssh =
|
54
|
+
ssh = double
|
55
55
|
|
56
56
|
locations = {
|
57
57
|
"1.2.3.4" => [
|
@@ -65,16 +65,32 @@ module CFTools::Tunnel
|
|
65
65
|
|
66
66
|
locations.each do |_, locs|
|
67
67
|
locs.each do |loc|
|
68
|
-
|
68
|
+
expect(loc).to receive(:stream_lines).with(ssh)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
stub(
|
72
|
+
gateway.stub(:ssh).and_yield(ssh)
|
73
73
|
|
74
74
|
entries << nil
|
75
75
|
|
76
76
|
subject.stream(locations)
|
77
77
|
end
|
78
|
+
|
79
|
+
context "when streaming fails" do
|
80
|
+
it "retries" do
|
81
|
+
called = 0
|
82
|
+
subject.stub(:stream_location) do
|
83
|
+
called += 1
|
84
|
+
raise "boom" if called == 1
|
85
|
+
end
|
86
|
+
|
87
|
+
entries << nil
|
88
|
+
|
89
|
+
subject.stream("1.2.3.4" => [])
|
90
|
+
|
91
|
+
expect(called).to eq(2)
|
92
|
+
end
|
93
|
+
end
|
78
94
|
end
|
79
95
|
end
|
80
96
|
end
|
@@ -23,15 +23,15 @@ describe CFTools::Tunnel::StreamLocation do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
describe "#stream_lines" do
|
26
|
-
let(:ssh) {
|
26
|
+
let(:ssh) { double }
|
27
27
|
|
28
28
|
it "tails the file under /var/vcap/sys/log" do
|
29
|
-
|
29
|
+
expect(ssh).to receive(:exec).with("tail -f /var/vcap/sys/log/#{path}")
|
30
30
|
subject.stream_lines(ssh)
|
31
31
|
end
|
32
32
|
|
33
33
|
it "yields log entries as lines come through the channel" do
|
34
|
-
stub(
|
34
|
+
ssh.stub(:exec).and_yield({}, :stdout, "foo\nbar\n")
|
35
35
|
|
36
36
|
lines = []
|
37
37
|
subject.stream_lines(ssh) do |entry|
|
@@ -43,10 +43,7 @@ describe CFTools::Tunnel::StreamLocation do
|
|
43
43
|
|
44
44
|
it "merges chunks that form a complete line" do
|
45
45
|
channel = {}
|
46
|
-
stub(
|
47
|
-
blk.call(channel, :stdout, "fo")
|
48
|
-
blk.call(channel, :stdout, "o\nbar\n")
|
49
|
-
end
|
46
|
+
ssh.stub(:exec).and_yield(channel, :stdout, "fo").and_yield(channel, :stdout, "o\nbar\n")
|
50
47
|
|
51
48
|
lines = []
|
52
49
|
subject.stream_lines(ssh) do |entry|
|
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
module CFTools::Tunnel
|
4
4
|
describe TunnelNATS do
|
5
|
-
let(:director) {
|
5
|
+
let(:director) { double :director, :director_uri => "http://example.com" }
|
6
6
|
|
7
7
|
let(:deployments) do
|
8
8
|
[{ "name" => "some-deployment", "releases" => [{ "name" => "cf-release" }] }]
|
@@ -26,55 +26,46 @@ MANIFEST
|
|
26
26
|
|
27
27
|
let(:tunneled_port) { 65535 }
|
28
28
|
|
29
|
-
let(:initial_client) {
|
29
|
+
let(:initial_client) { double }
|
30
30
|
|
31
31
|
before do
|
32
|
-
stub(
|
32
|
+
initial_client.stub(:token => CFoundry::AuthToken.new("initial token"))
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
stub(cli).tunnel_to { tunneled_port }
|
38
|
-
end
|
34
|
+
described_class.any_instance.stub(:connected_director => director)
|
35
|
+
described_class.any_instance.stub(:client => initial_client)
|
36
|
+
described_class.any_instance.stub(:tunnel_to => tunneled_port)
|
39
37
|
|
40
|
-
|
41
|
-
stub(cf).login { CFoundry::AuthToken.new(nil) }
|
42
|
-
end
|
38
|
+
CFoundry::V2::Client.any_instance.stub(:login => CFoundry::AuthToken.new(nil))
|
43
39
|
|
44
|
-
stub(
|
45
|
-
stub(
|
40
|
+
director.stub(:list_deployments => deployments)
|
41
|
+
director.stub(:get_deployment => { "manifest" => deployment })
|
46
42
|
end
|
47
43
|
|
48
44
|
it "connects to the given director" do
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
director
|
53
|
-
end
|
54
|
-
end
|
45
|
+
expect_any_instance_of(described_class).to \
|
46
|
+
receive(:connected_director).with("some-director.com", "someuser@somehost.com").
|
47
|
+
and_return(director)
|
55
48
|
|
56
49
|
cf %W[tunnel-nats some-director.com help --gateway someuser@somehost.com]
|
57
50
|
end
|
58
51
|
|
59
52
|
it "tunnels to the NATS server through the director" do
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
53
|
+
expect_any_instance_of(described_class).to \
|
54
|
+
receive(:tunnel_to).with("1.2.3.4", 5678, "someuser@somehost.com").
|
55
|
+
and_return(tunneled_port)
|
65
56
|
|
66
57
|
cf %W[tunnel-nats some-director.com help --gateway someuser@somehost.com]
|
67
58
|
end
|
68
59
|
|
69
60
|
it "logs in as the admin user from the deployment" do
|
70
|
-
client =
|
71
|
-
stub(
|
61
|
+
client = double
|
62
|
+
client.stub(:token => CFoundry::AuthToken.new("bar"))
|
72
63
|
|
73
|
-
|
64
|
+
expect(CFoundry::V2::Client).to receive(:new).with("https://api.cf.museum") do
|
74
65
|
client
|
75
66
|
end
|
76
67
|
|
77
|
-
|
68
|
+
expect(client).to receive(:login).with("someadmin", "somepass") do
|
78
69
|
CFoundry::AuthToken.new("foo")
|
79
70
|
end
|
80
71
|
|
@@ -82,14 +73,20 @@ MANIFEST
|
|
82
73
|
end
|
83
74
|
|
84
75
|
it "invokes the given command with the NATS credentials" do
|
85
|
-
|
86
|
-
|
76
|
+
cmd = described_class.new
|
77
|
+
described_class.stub(:new => cmd)
|
78
|
+
|
79
|
+
cmd.stub(:execute).and_call_original
|
80
|
+
|
81
|
+
expect(cmd).to receive(:execute).with(Mothership.commands[:tunnel_nats], anything, anything)
|
82
|
+
|
83
|
+
expect(cmd).to receive(:execute).with(
|
87
84
|
Mothership.commands[:target],
|
88
85
|
%w[
|
89
86
|
some-arg --flag some-val --user natsuser
|
90
87
|
--password natspass --port 65535
|
91
88
|
],
|
92
|
-
|
89
|
+
anything)
|
93
90
|
|
94
91
|
cf %W[tunnel-nats some-director.com target some-arg --flag some-val]
|
95
92
|
end
|
@@ -6,7 +6,7 @@ module CFTools::Tunnel
|
|
6
6
|
|
7
7
|
let(:director) { Bosh::Cli::Director.new(director_uri) }
|
8
8
|
|
9
|
-
let(:stream) {
|
9
|
+
let(:stream) { double }
|
10
10
|
|
11
11
|
let(:vms) do
|
12
12
|
[ { "ips" => ["1.2.3.4"], "job_name" => "cloud_controller", "index" => 0 },
|
@@ -32,29 +32,29 @@ module CFTools::Tunnel
|
|
32
32
|
end
|
33
33
|
|
34
34
|
before do
|
35
|
-
stub(
|
36
|
-
stub(
|
37
|
-
|
35
|
+
director.stub(:list_deployments => deployments)
|
36
|
+
director.stub(:fetch_vm_state => vms)
|
37
|
+
described_class.any_instance.stub(:connected_director => director)
|
38
38
|
|
39
|
-
stub(stream)
|
40
|
-
|
39
|
+
stream.stub(:stream)
|
40
|
+
described_class.any_instance.stub(:stream_for => stream)
|
41
41
|
end
|
42
42
|
|
43
43
|
it "connects to the given director" do
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
expect_any_instance_of(described_class).to \
|
45
|
+
receive(:connected_director).with(
|
46
|
+
"some-director.com", "someuser@somehost.com").
|
47
|
+
and_return(director)
|
48
48
|
|
49
49
|
cf %W[watch-logs some-director.com --gateway someuser@somehost.com]
|
50
50
|
end
|
51
51
|
|
52
52
|
context "when no gateway user/host is specified" do
|
53
53
|
it "defaults to vcap@director" do
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
expect_any_instance_of(described_class).to \
|
55
|
+
receive(:connected_director).with(
|
56
|
+
"some-director.com", "vcap@some-director.com").
|
57
|
+
and_return(director)
|
58
58
|
|
59
59
|
cf %W[watch-logs some-director.com]
|
60
60
|
end
|
@@ -71,11 +71,10 @@ module CFTools::Tunnel
|
|
71
71
|
|
72
72
|
context "when there are jobs to log" do
|
73
73
|
it "streams their locations" do
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
74
|
+
expect(stream).to receive(:stream).with(hash_including(
|
75
|
+
["cloud_controller", 0] => anything,
|
76
|
+
["dea_next", 0] => anything,
|
77
|
+
["dea_next", 1] => anything))
|
79
78
|
|
80
79
|
cf %W[watch-logs some-director.com]
|
81
80
|
end
|
@@ -100,11 +99,7 @@ module CFTools::Tunnel
|
|
100
99
|
%Q[{"message":"c","timestamp":#{entry3_time.to_f},"log_level":"error"}],
|
101
100
|
:stdout)
|
102
101
|
|
103
|
-
|
104
|
-
blk.call(entry1)
|
105
|
-
blk.call(entry2)
|
106
|
-
blk.call(entry3)
|
107
|
-
end
|
102
|
+
expect(stream).to receive(:stream).and_yield(entry1).and_yield(entry2).and_yield(entry3)
|
108
103
|
|
109
104
|
cf %W[watch-logs some-director.com]
|
110
105
|
|
@@ -112,6 +107,13 @@ module CFTools::Tunnel
|
|
112
107
|
expect(output).to say("dea_next/1 01:02:04 AM warn b\n")
|
113
108
|
expect(output).to say("dea_next/0 01:02:05 AM error c\n")
|
114
109
|
end
|
110
|
+
|
111
|
+
context "and components were specified" do
|
112
|
+
it "streams their locations" do
|
113
|
+
expect(stream).to receive(:stream).with(["cloud_controller", 0] => anything)
|
114
|
+
cf %W[watch-logs some-director.com cloud_controller]
|
115
|
+
end
|
116
|
+
end
|
115
117
|
end
|
116
118
|
end
|
117
119
|
end
|