diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-16 18:06:17 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-16 18:06:17 +0300 |
commit | 00c78fb814d7ce00989ac04edd6cdaa3239da284 (patch) | |
tree | f04920f08eb4e481ce27bd1d96862676dff735dc /spec/lib/gitlab/cluster | |
parent | d2ffc30fd583e86d4122bb5061098f4f3ca7b3f1 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib/gitlab/cluster')
-rw-r--r-- | spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb | 93 | ||||
-rw-r--r-- | spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb | 109 |
2 files changed, 202 insertions, 0 deletions
diff --git a/spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb b/spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb new file mode 100644 index 00000000000..038b72075ad --- /dev/null +++ b/spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# For easier debugging set `PUMA_DEBUG=1` + +describe Gitlab::Cluster::Mixins::PumaCluster do + PUMA_STARTUP_TIMEOUT = 30 + + context 'when running Puma in Cluster-mode' do + %i[USR1 USR2 INT HUP].each do |signal| + it "for #{signal} does execute phased restart block" do + with_puma(workers: 1) do |pid| + Process.kill(signal, pid) + + child_pid, child_status = Process.wait2(pid) + expect(child_pid).to eq(pid) + expect(child_status).to be_exited + expect(child_status.exitstatus).to eq(140) + end + end + end + end + + private + + def with_puma(workers:, timeout: PUMA_STARTUP_TIMEOUT) + with_puma_config(workers: workers) do |puma_rb| + cmdline = [ + "bundle", "exec", "puma", + "-C", puma_rb, + "-I", Rails.root.to_s + ] + + IO.popen(cmdline) do |process| + # wait for process to start: + # [2123] * Listening on tcp://127.0.0.1:0 + wait_for_output(process, /Listening on/, timeout: timeout) + consume_output(process) + + yield(process.pid) + ensure + Process.kill(:KILL, process.pid) unless process.eof? + end + end + end + + def with_puma_config(workers:) + Dir.mktmpdir do |dir| + File.write "#{dir}/puma.rb", <<-EOF + require './lib/gitlab/cluster/lifecycle_events' + require './lib/gitlab/cluster/mixins/puma_cluster' + + workers #{workers} + bind "tcp://127.0.0.1:0" + preload_app! + + app -> (env) { [404, {}, ['']] } + + Puma::Cluster.prepend(#{described_class}) + + Gitlab::Cluster::LifecycleEvents.on_before_phased_restart do + exit(140) + end + + # redirect stderr to stdout + $stderr.reopen($stdout) + EOF + + yield("#{dir}/puma.rb") + end + end + + def wait_for_output(process, output, timeout:) + Timeout.timeout(timeout) do + loop do + line = process.readline + puts "PUMA_DEBUG: #{line}" if ENV['PUMA_DEBUG'] + break if line =~ output + end + end + end + + def consume_output(process) + Thread.new do + loop do + line = process.readline + puts "PUMA_DEBUG: #{line}" if ENV['PUMA_DEBUG'] + end + rescue + end + end +end diff --git a/spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb b/spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb new file mode 100644 index 00000000000..43176e38b2b --- /dev/null +++ b/spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# For easier debugging set `UNICORN_DEBUG=1` + +describe Gitlab::Cluster::Mixins::UnicornHttpServer do + UNICORN_STARTUP_TIMEOUT = 10 + + context 'when running Unicorn' do + %i[USR2].each do |signal| + it "for #{signal} does execute phased restart block" do + with_unicorn(workers: 1) do |pid| + Process.kill(signal, pid) + + child_pid, child_status = Process.wait2(pid) + expect(child_pid).to eq(pid) + expect(child_status).to be_exited + expect(child_status.exitstatus).to eq(140) + end + end + end + + %i[QUIT TERM INT].each do |signal| + it "for #{signal} does not execute phased restart block" do + with_unicorn(workers: 1) do |pid| + Process.kill(signal, pid) + + child_pid, child_status = Process.wait2(pid) + expect(child_pid).to eq(pid) + expect(child_status).to be_exited + expect(child_status.exitstatus).to eq(0) + end + end + end + end + + private + + def with_unicorn(workers:, timeout: UNICORN_STARTUP_TIMEOUT) + with_unicorn_configs(workers: workers) do |unicorn_rb, config_ru| + cmdline = [ + "bundle", "exec", "unicorn", + "-I", Rails.root.to_s, + "-c", unicorn_rb, + config_ru + ] + + IO.popen(cmdline) do |process| + # wait for process to start: + # I, [2019-10-15T13:21:27.565225 #3089] INFO -- : master process ready + wait_for_output(process, /master process ready/, timeout: timeout) + consume_output(process) + + yield(process.pid) + ensure + Process.kill(:KILL, process.pid) unless process.eof? + end + end + end + + def with_unicorn_configs(workers:) + Dir.mktmpdir do |dir| + File.write "#{dir}/unicorn.rb", <<-EOF + require './lib/gitlab/cluster/lifecycle_events' + require './lib/gitlab/cluster/mixins/unicorn_http_server' + + worker_processes #{workers} + listen "127.0.0.1:0" + preload_app true + + Unicorn::HttpServer.prepend(#{described_class}) + + Gitlab::Cluster::LifecycleEvents.on_before_phased_restart do + exit(140) + end + + # redirect stderr to stdout + $stderr.reopen($stdout) + EOF + + File.write "#{dir}/config.ru", <<-EOF + run -> (env) { [404, {}, ['']] } + EOF + + yield("#{dir}/unicorn.rb", "#{dir}/config.ru") + end + end + + def wait_for_output(process, output, timeout:) + Timeout.timeout(timeout) do + loop do + line = process.readline + puts "UNICORN_DEBUG: #{line}" if ENV['UNICORN_DEBUG'] + break if line =~ output + end + end + end + + def consume_output(process) + Thread.new do + loop do + line = process.readline + puts "UNICORN_DEBUG: #{line}" if ENV['UNICORN_DEBUG'] + end + rescue + end + end +end |