dockerspec icon indicating copy to clipboard operation
dockerspec copied to clipboard

Infrataster doesn't work with ports other than 80

Open estahn opened this issue 7 years ago • 5 comments

Dockerspec Version

0.4.1

Ruby Version

ruby 2.4.0p0

Platform Details

Mac

Scenario

Testing a docker container exposing port 9000 with Infrataster.

Steps to Reproduce

    describe server(described_container) do

      describe http('/healthcheck') do
        it 'responds with works' do
          expect(response.body).to include 'WORKS'
        end
      end

    end

Expected Result

Serverspec on tag: "sha256:21afedc21ede0f4fb2e6416d83cf2f70b60e3fa3a6c275e1ec53a8f4f78e4e81"
    server '/sleepy_bose'
      http 'http://172.0.1.2:9000/healthcheck' with {:params=>{}, :method=>:get, :headers=>{}}

Actual Result

Serverspec on tag: "sha256:21afedc21ede0f4fb2e6416d83cf2f70b60e3fa3a6c275e1ec53a8f4f78e4e81"
    server '/sleepy_bose'
      http 'http:/healthcheck' with {:params=>{}, :method=>:get, :headers=>{}}

estahn avatar Mar 31 '17 20:03 estahn

Hi @estahn,

Try passing the complete URL to the http resource:

    describe server(described_container) do

      describe http('http://localhost:9000/healthcheck') do
        it 'responds with works' do
          expect(response.body).to include 'WORKS'
        end
      end

    end

That should work in theory. Let me know if not.

zuazo avatar Apr 01 '17 05:04 zuazo

It doesn't because the port is not mapped. dockerspec will need to look for a random available port and map the exposed container port. Then specify it in the server resource.

Also I'd like to avoid specifying the entire URL otherwise dockerspec becomes useless in this case.

Note: I currently use Infrataster without dockerspec and it works. I'm trying to integrate it in the context of dockerspec.

estahn avatar Apr 01 '17 06:04 estahn

Sorry @estahn, I misunderstood the issue.

Please, could you give me an example of Dockerfile/docker-compose.yml to reproduce the problem?

zuazo avatar Apr 01 '17 07:04 zuazo

@zuazo No worries. I don't use docker-compose, but i might start with it for my test cases.

The _spec files looks like this:

require 'dockerspec/infrataster'

describe 'thumbor' do
  before :all do
    image = Docker::Image.get(ENV['DOCKER_IMAGE'])

    set :os, family: :alpine
    set :backend, :docker
    set :docker_image, image.id
  end

  describe docker_run(tag: Docker::Image.get(ENV['DOCKER_IMAGE']).id) do
    describe server(described_container) do
      describe http("/healthcheck") do
        it 'responds with works' do
          expect(response.body).to include 'WORKS'
        end
      end

    end
  end

end

Call:

DOCKER_IMAGE=hipages/thumbor:6.3 bundle exec rspec

The docker image needs to be pulled before, but is currently not publicly available. You can use zanui/thumbor instead.

There is another issue which is kinda related to the port problem. It's not possible to access container via IP and port directly on Mac.

The current workaround i'm testing is from my old infrataster tests:

set :docker_container_create_options, {
  "AttachStdout" => true,
  "AttachStderr" => true,
  "PortBindings" => { "9000/tcp" => [{ "HostIp" => "0.0.0.0", "HostPort" => "9000" }]}
}

Basically exposing the port the host system like you suggested.

Any better idea would be appreciated.

UPDATE: I tested it with exposing the port to the host system and using describe http("http://127.0.0.1:9000/healthcheck") do which still runs into a Net::OpenTimeout: which suggest it won't override the address in the service resource when specifying it.

2) thumbor Serverspec on tag: "sha256:21afedc21ede0f4fb2e6416d83cf2f70b60e3fa3a6c275e1ec53a8f4f78e4e81" server '/infallible_ramanujan' http 'http://127.0.0.1:9000/healthcheck' with {:params=>{}, :method=>:get, :headers=>{}} responds with works
     Failure/Error: expect(response.body).to include 'WORKS'
     Faraday::ConnectionFailed:
       execution expired

     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/adapter/net_http.rb:78:in `perform_request'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/adapter/net_http.rb:38:in `block in call'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/adapter/net_http.rb:85:in `with_net_http_connection'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/adapter/net_http.rb:33:in `call'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/response.rb:8:in `call'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/response/logger.rb:26:in `call'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/request/url_encoded.rb:15:in `call'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/rack_builder.rb:139:in `build_response'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/connection.rb:377:in `run_request'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/faraday-0.11.0/lib/faraday/connection.rb:140:in `get'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/infrataster-0.3.2/lib/infrataster/contexts/http_context.rb:28:in `public_send'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/infrataster-0.3.2/lib/infrataster/contexts/http_context.rb:28:in `block in response'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/infrataster-0.3.2/lib/infrataster/server.rb:82:in `forward_port'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/infrataster-0.3.2/lib/infrataster/contexts/http_context.rb:8:in `response'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/infrataster-0.3.2/lib/infrataster/helpers/rspec_helper.rb:6:in `public_send'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/infrataster-0.3.2/lib/infrataster/helpers/rspec_helper.rb:6:in `method_missing'
     # ./spec/thumbor_spec.rb:47:in `block (5 levels) in <top (required)>'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:112:in `block in run'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:101:in `loop'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:101:in `run'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/rspec-retry-0.5.3/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
     # /Users/estahn/.rvm/gems/ruby-2.4.0/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:30:in `block (2 levels) in setup'
     # ------------------
     # --- Caused by: ---
     # Net::OpenTimeout:
     #   execution expired

estahn avatar Apr 01 '17 13:04 estahn

I got it working with some ugly workaround.

require 'dockerspec/infrataster'

Infrataster::Server.define('app', '127.0.0.1')
set :docker_container_create_options, {
  "PortBindings" => { "9000/tcp" => [{ "HostIp" => "0.0.0.0", "HostPort" => "9000" }]}
}

describe 'thumbor' do
  before :all do
    image = Docker::Image.get(ENV['DOCKER_IMAGE'])

    set :os, family: :alpine
    set :backend, :docker
    set :docker_image, image.id
  end

  describe docker_run(tag: Docker::Image.get(ENV['DOCKER_IMAGE']).id, wait: 1) do
    describe server('app') do
      describe http("http://app:9000/healthcheck") do
        it "responds content including 'WORKING'" do
          expect(response.body).to include('WORKING')
        end
      end
    end
  end
end

estahn avatar Apr 01 '17 15:04 estahn