Выполняется ли ruby_block повторно, когда количество повторных попыток превышает 0, а ignore_failure равно true? - PullRequest
0 голосов
/ 28 февраля 2020

Существует рецепт шеф-повара с ruby -блоком. ruby -блок выполняется до тех пор, пока не будет установлено сокетное соединение (повтор 10). Если соединение не может быть установлено, ruby -блок не должен выйти из строя (ignore_failure).

Пример:

ruby_block 'wait for service' do
  block do
    require 'socket'
    require 'timeout'
    Timeout.timeout(2) do
      s = TCPSocket.new('127.0.0.1', 8080)
      s.close
    end
  end
  retries 10
  retry_delay 5
  ignore_failure true
  action :run
end

В документации шеф-повара не ясно, выполняется ли блок ruby повторно или нет, если для ignore_failure установлено значение true.

Обновление

Когда сценарий выполняется и порт 8080 не прослушивает службу, выполнение рецепта шеф-повара продолжается после первой попытки со следующим сообщением:

ERROR: ruby_block[wait for service] (cookbook::wait_for_service line 1) had an error: Errno::ECONNREFUSED: Connection refused - connect(2) for "127.0.0.1" port 8080; ignore_failure is set, continuing

...

Error executing action run on resource 'ruby_block[wait for service]'

Errno::ECONNREFUSED
-------------------
Connection refused - connect(2) for "127.0.0.1" port 8080

...

Из-за объявления ruby_block я бы сказал, что ruby выполняется 10 раз, прежде чем сообщать о ERROR.

Ответы [ 2 ]

1 голос
/ 02 марта 2020

Я протестировал ваш сценарий с версией Chef 12.19.36 , и действительно случается так, что если указаны ignore_failure и retries, только ignore_failure применяется при retries игнорируется.

Также здесь документация Chef не ясна об этом конкретном c сценарии, и поэтому решить эту проблему невозможно,

В любом случае вы можно решить вручную, реализовав retries и retry_delay logi c следующим образом:

ruby_block 'wait for service' do
      block do
        require 'socket'
        require 'timeout'

        retry_delay = 5
        retries = 10

        1.upto(retries) do |n|
          err_msg = ""
          begin
            Timeout::timeout(retry_delay) do
              begin
                s = TCPSocket.new('8.8.8.8', 52)
                s.close
                puts("Service is listening on")
                break
              rescue Errno::ECONNREFUSED
                err_msg = "Port is open but no service is listening on"
              rescue Errno::EHOSTUNREACH
                err_msg =  "Unable to connect to the service"
              end
            end
          rescue Timeout::Error
            err_msg = "Timeout reached"
          end

          if n == retries
            raise "Unabled to reach server in #{retries} attempts"
          else
            puts "Failed to reach server on attempt [#{n}/#{retries}]. Cause is: [#{err_msg}]. Waiting #{retry_delay} seconds and retry."
            sleep(retry_delay)
          end

        end
      end
      ignore_failure true
      action :run
    end

Вы также можете улучшить код, создав общую функцию execute_with_retry с лямбда-функцией в качестве входных данных для простого повторного использования этой логики c в ваших рецептах при необходимости.

1 голос
/ 28 февраля 2020

Мой тест доказывает, что повторные попытки не имеют никакого эффекта. Блок выполняется только один раз из-за сбоя соединения с сокетом.

...