spec/kontena/cli/services/exec_command_spec.rb in kontena-cli-1.4.0.pre1 vs spec/kontena/cli/services/exec_command_spec.rb in kontena-cli-1.4.0.pre2

- old
+ new

@@ -1,59 +1,11 @@ -require 'kontena/websocket/client' require 'kontena/cli/services/exec_command' describe Kontena::Cli::Services::ExecCommand do include ClientHelpers include OutputHelpers - let(:ws_client_class) do - Class.new do - - Event = Struct.new(:data) - - def initialize - @callbacks = {} - end - - def on(callback, &block) - @callbacks[callback] = block - if callback == :open - Thread.new { - sleep 0.01 - @callbacks[:open].call - } - end - end - - def connect ; end - - def receive_message(msg) - @callbacks[:message].call(Event.new(JSON.dump(msg))) - rescue => exc - STDERR.puts exc.message - end - end - end - - let(:ws_client) do - ws_client_class.new - end - - let(:master_url) do - subject.require_current_master.url.gsub('http', 'ws') - end - - def respond_ok(ws_client) - ws_client.receive_message({'stream' => 'stdout', 'chunk' => "ok\n"}) - ws_client.receive_message({'exit' => 0}) - end - - def respond_error(ws_client) - ws_client.receive_message({'stream' => 'stderr', 'chunk' => "error\n"}) - ws_client.receive_message({'exit' => 1}) - end - context "For a service with one running instance" do let :service_containers do { 'containers' => [ { 'id' => 'test-grid/host/test-service.container-1', @@ -67,25 +19,20 @@ before do expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) end it "Executes on the running container by default" do - 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) - expect(ws_client).to receive(:text) do |foo| - ws_client.receive_message({'stream' => 'stdout', 'chunk' => "ok\n"}) - ws_client.receive_message({'exit' => 0}) - end - - expect { - subject.run(['test-service', 'test']) - }.to output("ok\n").to_stdout + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ).and_return(0) + expect{subject.run(['test-service', 'test'])}.to_not exit_with_error end end context "For a service with multiple running instances" do let :service_containers do - { 'containers' => [ + [ { 'id' => 'test-grid/host/test-service.container-1', 'name' => 'test-service.container-1', 'instance_number' => 1, 'status' => 'running', @@ -100,128 +47,110 @@ 'id' => 'test-grid/host/test-service.container-3', 'name' => 'test-service.container-3', 'instance_number' => 3, 'status' => 'running', }, - ] } + ] end it "Executes on the first running container by default" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) - 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) - expect(ws_client).to receive(:text) do - respond_ok(ws_client) + expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return('containers' => service_containers) + + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ) do + puts 'ok 1' + 0 end - expect { + + expect{ subject.run(['test-service', 'test']) - }.to output("ok\n").to_stdout + }.to output_lines [ 'ok 1' ] end it "Executes on the first running container, even if they are ordered differently" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return({'containers' => service_containers['containers'].reverse }) - 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) - expect(ws_client).to receive(:text) do - respond_ok(ws_client) - end - expect { - subject.run(['test-service', 'test']) - }.to output("ok\n").to_stdout + expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return('containers' => service_containers.reverse) + + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ).and_return(0) + expect{subject.run(['test-service', 'test'])}.to_not exit_with_error end - it "Executes on the first running container if given" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) - 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) - expect(ws_client).to receive(:text) do - respond_ok(ws_client) + context do + before do + expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return('containers' => service_containers) end - expect { - subject.run(['test-service', 'test']) - }.to output("ok\n").to_stdout - end - it "Executes on the second running container if given" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) - 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) - expect(ws_client).to receive(:text) do - respond_ok(ws_client) + it "Executes on the first running container if given" do + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ).and_return(0) + expect{subject.run(['--instance=1', 'test-service', 'test'])}.to_not exit_with_error end - expect { - subject.run(['--instance', '2', 'test-service', 'test']) - }.to output("ok\n").to_stdout - end - it "Errors on a nonexistant container if given" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) + it "Executes on the second running container if given" do + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'], + interactive: false, shell: false, tty: false, + ).and_return(0) + expect{subject.run(['--instance=2', 'test-service', 'test'])}.to_not exit_with_error + end - 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 - end + it "Errors on a nonexistant container if given" do + 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 + end - it "Executes on each running container" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) + it "Executes on each running container" do + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ).and_return(0) + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'], + interactive: false, shell: false, tty: false, + ).and_return(0) + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-3', ['test'], + interactive: false, shell: false, tty: false, + ).and_return(0) - 3.times do |i| - ws_client = ws_client_class.new - 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) - expect(ws_client).to receive(:text) do - ws_client.receive_message({'stream' => 'stdout', 'chunk' => "test#{i + 1}\n"}) - ws_client.receive_message({'exit' => 0}) - end + subject.run(['--silent', '--all', 'test-service', 'test']) end - expect { - subject.run(['--silent', '--all', 'test-service', 'test']) - }.to output("test1\ntest2\ntest3\n").to_stdout - end + it "Stops if the first container fails" do + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ) { $stderr << 'error'; 1 } - it "Stops if the first container fails" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) - 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) - expect(ws_client).to receive(:text) do - respond_error(ws_client) + expect { + subject.run(['--silent', '--all', 'test-service', 'test']) + }.to exit_with_error.and output("error").to_stderr end - expect { - subject.run(['--silent', '--all', 'test-service', 'test']) - }.to output("error\n").to_stderr - end - it "Stops if the second container fails" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) - i = 1 - [:ok, :err].each do |status| - ws_client = ws_client_class.new - 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) - expect(ws_client).to receive(:text) do - if status == :ok - respond_ok(ws_client) - else - respond_error(ws_client) - end - end - i += 1 + it "Stops if the second container fails" do + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ) { $stdout << 'ok 1'; 0 } + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'], + interactive: false, shell: false, tty: false, + ) { $stderr << 'error 2'; 1 } + + expect { + subject.run(['--silent', '--all', 'test-service', 'test']) + }.to exit_with_error.and output("ok 1").to_stdout.and output("error 2").to_stderr end - expect { - subject.run(['--silent', '--all', 'test-service', 'test']) - }.to output("ok\n").to_stdout.and output("error\n").to_stderr - end - it "Keeps going if the second container fails when using --skip" do - expect(client).to receive(:get).with('services/test-grid/null/test-service/containers').and_return(service_containers) + it "Keeps going if the second container fails when using --skip" do + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-1', ['test'], + interactive: false, shell: false, tty: false, + ) { puts 'ok 1'; 0} + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-2', ['test'], + interactive: false, shell: false, tty: false, + ) { puts 'err 2'; 2 } + expect(subject).to receive(:container_exec).with('test-grid/host/test-service.container-3', ['test'], + interactive: false, shell: false, tty: false, + ) { puts 'ok 3'; 0 } - i = 1 - [:ok, :err, :ok].each do |status| - ws_client = ws_client_class.new - 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) - expect(ws_client).to receive(:text) do - if status == :ok - respond_ok(ws_client) - else - respond_error(ws_client) - end - end - i += 1 + expect { + subject.run(['--silent', '--all', '--skip', 'test-service', 'test']) + }.to exit_with_error.and output_lines ['ok 1', 'err 2', 'ok 3'] end - expect { - subject.run(['--silent', '--all', '--skip', 'test-service', 'test']) - }.to output("ok\nok\n").to_stdout.and output("error\n").to_stderr end end end