'Error executing ruby script in docker environment

I have a script that is supposed to just check when my elasticsearch instance/container is up and running. But there appears to be some issue with the calls, as I get the error:

TypeError: Failed to open TCP connection to : (no implicit conversion of nil into String)

Here is the ruby code:

class AwaitEs
  def self.call(uri)
    AwaitEs.new(uri).wait

  def initialize(uri)  
    @uri = URI.parse("#{uri}/_cluster/health")

  def wait
    status = get_status
    until VALID_STATUS.include? status
      puts 'Still waiting ...'
      sleep 5
      status = get_status
 
  def get_status
    HEADER = {'Content-Type' => 'application/json' }.freeze
    http = Net::HTTP.new(uri.host, uri.port)
    request = Net::HTTP::Get.new(uri.request_uri, HEADER)

    begin
      res = http.request(request)
    rescue Errno:ECONNREFUSED
      return 'red'
    end

    result = JSON.parse(response.body)
    result['status']

  private

  attr_reader :uri

  VALID_STATUS = %w[yellow green].freeze

AwaitEs.call ARGV[0]

The error occurs on the line res = http.request(request). It appears that there is no host or port information. But when I check uri.host=elasticsearch and uri.port=9200, where elasticsearch is the name of the docker service for ES. When I change the host to localhost, the error disappears, but instead I get Connection refused instead (because the waiter docker does not see the elasticsearch docker on localhost.

The docker container calls the ruby script using a shell script named start.sh

#!/bin/sh
for file in `ls ./??_*.rb`; do
  ruby $file `http://elasticsearch:9200`
done

The docker-compose.yml:

volumes:
  es_data: {}

services:
  elasticsearch:
    image: elasticsearch:5.4.3
    ports: ['9200:9200', '9300:9300']
    volumes:
      - es_data:/usr/share/elsticsearch/data
  waiter:
    build:
      context: ./waiter/

Finally the dockerfile for waiter:

FROM jruby:9.1.15-alpine
ADD ./ /app/
WORKDIR /app
CMD bash -c "./start.sh"

When I run this, I get the error:



Solution 1:[1]

You need to reference uri correctly in the get_status method as an instance variable or pass it along with the get_status method.

Change the following:

def get_status
    HEADER = {'Content-Type' => 'application/json' }.freeze
    http = Net::HTTP.new(uri.host, uri.port)
    request = Net::HTTP::Get.new(uri.request_uri, HEADER)

    begin
      res = http.request(request)
    rescue Errno:ECONNREFUSED
      return 'red'
    end

    result = JSON.parse(response.body)
    result['status']

To use an instance variable @uri, like this:

def get_status
    HEADER = {'Content-Type' => 'application/json' }.freeze
    http = Net::HTTP.new(@uri.host, @uri.port)
    request = Net::HTTP::Get.new(@uri.request_uri, HEADER)

    begin
      res = http.request(request)
    rescue Errno:ECONNREFUSED
      return 'red'
    end

    result = JSON.parse(response.body)
    result['status']

Or you can pass it along as a method parameter. In that case, change this:

 def wait
    status = get_status
    until VALID_STATUS.include? status
      puts 'Still waiting ...'
      sleep 5
      status = get_status
 
  def get_status
    HEADER = {'Content-Type' => 'application/json' }.freeze
    http = Net::HTTP.new(uri.host, uri.port)
    request = Net::HTTP::Get.new(uri.request_uri, HEADER)

    begin
      res = http.request(request)
    rescue Errno:ECONNREFUSED
      return 'red'
    end

    result = JSON.parse(response.body)
    result['status']

to this:

 def wait
    status = get_status(@uri)
    until VALID_STATUS.include? status
      puts 'Still waiting ...'
      sleep 5
      status = get_status(@uri)
 
  def get_status(uri)
    HEADER = {'Content-Type' => 'application/json' }.freeze
    http = Net::HTTP.new(uri.host, uri.port)
    request = Net::HTTP::Get.new(uri.request_uri, HEADER)

    begin
      res = http.request(request)
    rescue Errno:ECONNREFUSED
      return 'red'
    end

    result = JSON.parse(response.body)
    result['status']

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DogEatDog