kontena-cli 1.4.0.pre1 → 1.4.0.pre2

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,57 +1,9 @@
1
- require 'kontena/websocket/client'
2
1
  require 'kontena/cli/services/exec_command'
3
2
 
4
3
  describe Kontena::Cli::Services::ExecCommand do
5
4
  include ClientHelpers
6
5
  include OutputHelpers
7
6
 
8
- let(:ws_client_class) do
9
- Class.new do
10
-
11
- Event = Struct.new(:data)
12
-
13
- def initialize
14
- @callbacks = {}
15
- end
16
-
17
- def on(callback, &block)
18
- @callbacks[callback] = block
19
- if callback == :open
20
- Thread.new {
21
- sleep 0.01
22
- @callbacks[:open].call
23
- }
24
- end
25
- end
26
-
27
- def connect ; end
28
-
29
- def receive_message(msg)
30
- @callbacks[:message].call(Event.new(JSON.dump(msg)))
31
- rescue => exc
32
- STDERR.puts exc.message
33
- end
34
- end
35
- end
36
-
37
- let(:ws_client) do
38
- ws_client_class.new
39
- end
40
-
41
- let(:master_url) do
42
- subject.require_current_master.url.gsub('http', 'ws')
43
- end
44
-
45
- def respond_ok(ws_client)
46
- ws_client.receive_message({'stream' => 'stdout', 'chunk' => "ok\n"})
47
- ws_client.receive_message({'exit' => 0})
48
- end
49
-
50
- def respond_error(ws_client)
51
- ws_client.receive_message({'stream' => 'stderr', 'chunk' => "error\n"})
52
- ws_client.receive_message({'exit' => 1})
53
- end
54
-
55
7
  context "For a service with one running instance" do
56
8
  let :service_containers do
57
9
  { 'containers' => [
@@ -69,21 +21,16 @@ describe Kontena::Cli::Services::ExecCommand do
69
21
  end
70
22
 
71
23
  it "Executes on the running container by default" do
72
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-1/exec", anything).and_return(ws_client)
73
- expect(ws_client).to receive(:text) do |foo|
74
- ws_client.receive_message({'stream' => 'stdout', 'chunk' => "ok\n"})
75
- ws_client.receive_message({'exit' => 0})
76
- end
77
-
78
- expect {
79
- subject.run(['test-service', 'test'])
80
- }.to output("ok\n").to_stdout
24
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
25
+ interactive: false, shell: false, tty: false,
26
+ ).and_return(0)
27
+ expect{subject.run(['test-service', 'test'])}.to_not exit_with_error
81
28
  end
82
29
  end
83
30
 
84
31
  context "For a service with multiple running instances" do
85
32
  let :service_containers do
86
- { 'containers' => [
33
+ [
87
34
  {
88
35
  'id' => 'test-grid/host/test-service.container-1',
89
36
  'name' => 'test-service.container-1',
@@ -102,126 +49,108 @@ describe Kontena::Cli::Services::ExecCommand do
102
49
  'instance_number' => 3,
103
50
  'status' => 'running',
104
51
  },
105
- ] }
52
+ ]
106
53
  end
107
54
 
108
55
  it "Executes on the first running container by default" do
109
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
110
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-1/exec", anything).and_return(ws_client)
111
- expect(ws_client).to receive(:text) do
112
- respond_ok(ws_client)
56
+ expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return('containers' => service_containers)
57
+
58
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
59
+ interactive: false, shell: false, tty: false,
60
+ ) do
61
+ puts 'ok 1'
62
+ 0
113
63
  end
114
- expect {
64
+
65
+ expect{
115
66
  subject.run(['test-service', 'test'])
116
- }.to output("ok\n").to_stdout
67
+ }.to output_lines [ 'ok 1' ]
117
68
  end
118
69
 
119
70
  it "Executes on the first running container, even if they are ordered differently" do
120
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return({'containers' => service_containers['containers'].reverse })
121
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-1/exec", anything).and_return(ws_client)
122
- expect(ws_client).to receive(:text) do
123
- respond_ok(ws_client)
124
- end
125
- expect {
126
- subject.run(['test-service', 'test'])
127
- }.to output("ok\n").to_stdout
71
+ expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return('containers' => service_containers.reverse)
72
+
73
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
74
+ interactive: false, shell: false, tty: false,
75
+ ).and_return(0)
76
+ expect{subject.run(['test-service', 'test'])}.to_not exit_with_error
128
77
  end
129
78
 
130
- it "Executes on the first running container if given" do
131
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
132
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-1/exec", anything).and_return(ws_client)
133
- expect(ws_client).to receive(:text) do
134
- respond_ok(ws_client)
79
+ context do
80
+ before do
81
+ expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return('containers' => service_containers)
135
82
  end
136
- expect {
137
- subject.run(['test-service', 'test'])
138
- }.to output("ok\n").to_stdout
139
- end
140
83
 
141
- it "Executes on the second running container if given" do
142
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
143
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-2/exec", anything).and_return(ws_client)
144
- expect(ws_client).to receive(:text) do
145
- respond_ok(ws_client)
84
+ it "Executes on the first running container if given" do
85
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
86
+ interactive: false, shell: false, tty: false,
87
+ ).and_return(0)
88
+ expect{subject.run(['--instance=1', 'test-service', 'test'])}.to_not exit_with_error
146
89
  end
147
- expect {
148
- subject.run(['--instance', '2', 'test-service', 'test'])
149
- }.to output("ok\n").to_stdout
150
- end
151
90
 
152
- it "Errors on a nonexistant container if given" do
153
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
91
+ it "Executes on the second running container if given" do
92
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'],
93
+ interactive: false, shell: false, tty: false,
94
+ ).and_return(0)
95
+ expect{subject.run(['--instance=2', 'test-service', 'test'])}.to_not exit_with_error
96
+ end
154
97
 
155
- expect{subject.run(['--instance=4', 'test-service', 'test'])}.to exit_with_error.and output(/Service test-service does not have container instance 4/).to_stderr
156
- end
98
+ it "Errors on a nonexistant container if given" do
99
+ expect{subject.run(['--instance=4', 'test-service', 'test'])}.to exit_with_error.and output(/Service test-service does not have container instance 4/).to_stderr
100
+ end
157
101
 
158
- it "Executes on each running container" do
159
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
102
+ it "Executes on each running container" do
103
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
104
+ interactive: false, shell: false, tty: false,
105
+ ).and_return(0)
106
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'],
107
+ interactive: false, shell: false, tty: false,
108
+ ).and_return(0)
109
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-3', ['test'],
110
+ interactive: false, shell: false, tty: false,
111
+ ).and_return(0)
160
112
 
161
- 3.times do |i|
162
- ws_client = ws_client_class.new
163
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-#{i + 1}/exec", anything).and_return(ws_client)
164
- expect(ws_client).to receive(:text) do
165
- ws_client.receive_message({'stream' => 'stdout', 'chunk' => "test#{i + 1}\n"})
166
- ws_client.receive_message({'exit' => 0})
167
- end
113
+ subject.run(['--silent', '--all', 'test-service', 'test'])
168
114
  end
169
115
 
170
- expect {
171
- subject.run(['--silent', '--all', 'test-service', 'test'])
172
- }.to output("test1\ntest2\ntest3\n").to_stdout
173
- end
116
+ it "Stops if the first container fails" do
117
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
118
+ interactive: false, shell: false, tty: false,
119
+ ) { $stderr << 'error'; 1 }
174
120
 
175
- it "Stops if the first container fails" do
176
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
177
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-1/exec", anything).and_return(ws_client)
178
- expect(ws_client).to receive(:text) do
179
- respond_error(ws_client)
121
+ expect {
122
+ subject.run(['--silent', '--all', 'test-service', 'test'])
123
+ }.to exit_with_error.and output("error").to_stderr
180
124
  end
181
- expect {
182
- subject.run(['--silent', '--all', 'test-service', 'test'])
183
- }.to output("error\n").to_stderr
184
- end
185
125
 
186
- it "Stops if the second container fails" do
187
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
188
- i = 1
189
- [:ok, :err].each do |status|
190
- ws_client = ws_client_class.new
191
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-#{i}/exec", anything).and_return(ws_client)
192
- expect(ws_client).to receive(:text) do
193
- if status == :ok
194
- respond_ok(ws_client)
195
- else
196
- respond_error(ws_client)
197
- end
198
- end
199
- i += 1
126
+ it "Stops if the second container fails" do
127
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
128
+ interactive: false, shell: false, tty: false,
129
+ ) { $stdout << 'ok 1'; 0 }
130
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'],
131
+ interactive: false, shell: false, tty: false,
132
+ ) { $stderr << 'error 2'; 1 }
133
+
134
+ expect {
135
+ subject.run(['--silent', '--all', 'test-service', 'test'])
136
+ }.to exit_with_error.and output("ok 1").to_stdout.and output("error 2").to_stderr
200
137
  end
201
- expect {
202
- subject.run(['--silent', '--all', 'test-service', 'test'])
203
- }.to output("ok\n").to_stdout.and output("error\n").to_stderr
204
- end
205
-
206
- it "Keeps going if the second container fails when using --skip" do
207
- expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers)
208
138
 
209
- i = 1
210
- [:ok, :err, :ok].each do |status|
211
- ws_client = ws_client_class.new
212
- expect(Kontena::Websocket::Client).to receive(:new).with("#{master_url}v1/containers/test-grid/host/test-service.container-#{i}/exec", anything).and_return(ws_client)
213
- expect(ws_client).to receive(:text) do
214
- if status == :ok
215
- respond_ok(ws_client)
216
- else
217
- respond_error(ws_client)
218
- end
219
- end
220
- i += 1
139
+ it "Keeps going if the second container fails when using --skip" do
140
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'],
141
+ interactive: false, shell: false, tty: false,
142
+ ) { puts 'ok 1'; 0}
143
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'],
144
+ interactive: false, shell: false, tty: false,
145
+ ) { puts 'err 2'; 2 }
146
+ expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-3', ['test'],
147
+ interactive: false, shell: false, tty: false,
148
+ ) { puts 'ok 3'; 0 }
149
+
150
+ expect {
151
+ subject.run(['--silent', '--all', '--skip', 'test-service', 'test'])
152
+ }.to exit_with_error.and output_lines ['ok 1', 'err 2', 'ok 3']
221
153
  end
222
- expect {
223
- subject.run(['--silent', '--all', '--skip', 'test-service', 'test'])
224
- }.to output("ok\nok\n").to_stdout.and output("error\n").to_stderr
225
154
  end
226
155
  end
227
156
  end
@@ -9,6 +9,8 @@ module ClientHelpers
9
9
  instance_double(Kontena::Client, :client)
10
10
  end
11
11
 
12
+ base.let(:master_url) { 'http://someurl.example.com/' }
13
+
12
14
  base.let(:token) do
13
15
  '1234567'
14
16
  end
@@ -21,17 +23,18 @@ module ClientHelpers
21
23
  {'current_server' => 'alias',
22
24
  'current_account' => 'kontena',
23
25
  'servers' => [
24
- {'name' => 'some_master', 'url' => 'http://someurl.example.com'},
25
- {'name' => 'alias', 'url' => 'http://someurl.example.com/', 'token' => token, 'account' => 'master', 'grid' => current_grid},
26
+ {'name' => 'some_master', 'url' => master_url },
27
+ {'name' => 'alias', 'url' => master_url, 'token' => token, 'account' => 'master', 'grid' => current_grid},
26
28
  ]
27
29
  }
28
30
  end
29
31
 
30
32
  base.before(:each) do
33
+ master_host = URI(master_url).host
31
34
  RSpec::Mocks.space.proxy_for(File).reset
32
35
  allow(subject).to receive(:client).and_return(client)
33
36
  allow(subject).to receive(:current_grid).and_return(current_grid)
34
- allow(File).to receive(:exist?).with(File.join(Dir.home, '.kontena/certs/someurl.example.com.pem')).and_return(false)
37
+ allow(File).to receive(:exist?).with(File.join(Dir.home, ".kontena/certs/#{master_host}.pem")).and_return(false)
35
38
  allow(File).to receive(:exist?).with(File.join(Dir.home, '.kontena_client.json')).and_return(true)
36
39
  allow(File).to receive(:readable?).with(File.join(Dir.home, '.kontena_client.json')).and_return(true)
37
40
  allow(File).to receive(:read).and_call_original
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kontena-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0.pre1
4
+ version: 1.4.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kontena, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-26 00:00:00.000000000 Z
11
+ date: 2017-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -193,19 +193,19 @@ dependencies:
193
193
  - !ruby/object:Gem::Version
194
194
  version: 0.8.0
195
195
  - !ruby/object:Gem::Dependency
196
- name: websocket-driver-kontena
196
+ name: kontena-websocket-client
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - '='
199
+ - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: 0.6.5
201
+ version: 0.1.0
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - '='
206
+ - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: 0.6.5
208
+ version: 0.1.0
209
209
  description: Command-line client for the Kontena container and microservices platform
210
210
  email:
211
211
  - info@kontena.io
@@ -517,8 +517,6 @@ files:
517
517
  - lib/kontena/stacks_cache.rb
518
518
  - lib/kontena/stacks_client.rb
519
519
  - lib/kontena/util.rb
520
- - lib/kontena/websocket/client.rb
521
- - lib/kontena/websocket/client/connection.rb
522
520
  - lib/kontena_cli.rb
523
521
  - omnibus/.gitignore
524
522
  - omnibus/.kitchen.yml
@@ -590,6 +588,7 @@ files:
590
588
  - spec/kontena/cli/cloud/logout_command_spec.rb
591
589
  - spec/kontena/cli/cloud/master/add_command_spec.rb
592
590
  - spec/kontena/cli/common_spec.rb
591
+ - spec/kontena/cli/containers/exec_command_spec.rb
593
592
  - spec/kontena/cli/containers/list_command_spec.rb
594
593
  - spec/kontena/cli/containers/logs_command_spec.rb
595
594
  - spec/kontena/cli/etcd/health_command_spec.rb
@@ -756,6 +755,7 @@ test_files:
756
755
  - spec/kontena/cli/cloud/logout_command_spec.rb
757
756
  - spec/kontena/cli/cloud/master/add_command_spec.rb
758
757
  - spec/kontena/cli/common_spec.rb
758
+ - spec/kontena/cli/containers/exec_command_spec.rb
759
759
  - spec/kontena/cli/containers/list_command_spec.rb
760
760
  - spec/kontena/cli/containers/logs_command_spec.rb
761
761
  - spec/kontena/cli/etcd/health_command_spec.rb
@@ -1,12 +0,0 @@
1
- require 'websocket/driver'
2
- module Kontena
3
- module Websocket
4
- module Client
5
- def self.new(*args)
6
- Connection.new(*args)
7
- end
8
- end
9
- end
10
- end
11
-
12
- require_relative 'client/connection'
@@ -1,65 +0,0 @@
1
- require 'forwardable'
2
- require 'socket'
3
- require 'openssl'
4
-
5
- module Kontena
6
- module Websocket
7
- module Client
8
- class Connection
9
- extend Forwardable
10
-
11
- FRAME_SIZE = 1024
12
-
13
- attr_reader :url
14
-
15
- # @param [String] url
16
- # @param [Hash] options
17
- def initialize(url, options = {})
18
- @options = options
19
- @url = url
20
- @client = ::WebSocket::Driver.client(self)
21
- if headers = options[:headers]
22
- headers.each do |k, v|
23
- @client.set_header(k, v)
24
- end
25
- end
26
- end
27
-
28
- def connect
29
- uri = URI.parse(@url)
30
- port = uri.port || (uri.scheme == "ws" ? 80 : 443)
31
- @socket = ::TCPSocket.new(uri.host, port)
32
- if uri.scheme == "wss"
33
- ctx = ::OpenSSL::SSL::SSLContext.new
34
- ctx.ssl_version = @options[:ssl_version] if @options[:ssl_version]
35
- ctx.verify_mode = @options[:verify_mode] if @options[:verify_mode]
36
- cert_store = ::OpenSSL::X509::Store.new
37
- cert_store.set_default_paths
38
- ctx.cert_store = cert_store
39
- @socket = ::OpenSSL::SSL::SSLSocket.new(@socket, ctx)
40
- @socket.connect
41
- end
42
- @client.start
43
- Thread.new { self.read_socket }
44
- end
45
-
46
- def_delegators :@client, :text, :binary, :ping, :close, :protocol, :on
47
-
48
- def write(buffer)
49
- @socket.write(buffer)
50
- end
51
-
52
- def read_socket
53
- loop do
54
- begin
55
- @client.parse(@socket.readpartial(FRAME_SIZE))
56
- rescue EOFError
57
- break
58
- end
59
- end
60
- end
61
- end
62
- end
63
- end
64
- end
65
-