dockerspec
dockerspec copied to clipboard
Infrataster doesn't work with ports other than 80
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=>{}}
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.
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.
Sorry @estahn, I misunderstood the issue.
Please, could you give me an example of Dockerfile/docker-compose.yml to reproduce the problem?
@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
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