Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pass the pact dir to the server when writing pacts #79

Closed
wants to merge 2 commits into from

Conversation

iamleeg
Copy link

@iamleeg iamleeg commented Aug 4, 2017

The ruby pact-mock-server requires pact_dir to be supplied when writing pacts, otherwise this error is encountered:

Error: {"message":"Error ocurred in mock service: Pact::ConsumerContractWriterError - Please indicate the directory to write the pact to by specifying the pact_dir field","backtrace": ...}

The JS client was not sending that option, expecting to start a pact-node mock itself and configure its pact dir on construction. This change adds that option, so pact-js can be used with either mock service implementation.

@mefellows
Copy link
Member

Thanks, I'll take a look over the weekend. are you able to elaborate a bit further on your use case?

@iamleeg
Copy link
Author

iamleeg commented Aug 15, 2017

Hi, thanks for looking into my issue. My use case is that I'm integrating pact into my organisation's CI workflow. We use Jenkins to launch the tests, and the test environment is set up with docker-compose. I'm using the pactfoundation/pact-mock-service Docker image, which hosts a pact mock on port 80. I therefore don't need pact-js to launch the mock, just to communicate with the one that's running in my docker-compose cluster.

As noted above, the pact server running in that docker image doesn't take the pacts dir as a constructor/setup option, it's passed as described in the gist you've found and commented on. If you don't pass it, then the described error occurs.

I appreciate now that this may be a failure of the pact server, after your comment on that gist that the pact_dir options isn't in the spec. I'm checking out the server code to dig in more.

@iamleeg
Copy link
Author

iamleeg commented Aug 15, 2017

What I've seen is that on writing the pact, the server merges the post body with the default options to control how the pact is written. Therefore the pact_dir field in the request is required iff the pact_dir configuration wasn't given in setting up the service.

I think that gives me enough information to work around the problem I had. I also think it means my fix in the PR would be sufficient, but that it is more likely the case that this is a bug in the server: letting the client control where files get written seems dangerous. I'll raise an issue over there.

@mefellows
Copy link
Member

Thanks @iamleeg, this is a use case I had't considered. I'd like to think more on this one, however i'm leaning towards supporting this as an option. I can see the benefits.

@bethesque
Copy link
Member

It makes sense to me to be able to pass in the option, as all the other similar options are configurable the same way.

@bethesque
Copy link
Member

I can provide a default pact dir to the docker image if that would help. It will just be awkward getting the file back out again. But I guess it will stop the error happening.

@bethesque
Copy link
Member

@mefellows notifications on gists don't work, so I didn't see your question :(

The pact dir isn't part of the pact spec, it's an implementation detail of the ruby mock service. You can either provide it at startup via the command line, or when you tell the mock service to write the pact.

@bethesque
Copy link
Member

I'm a bit confused because when I run docker-compose up from the pact-foundation/pact-mock-service dir, and then run curl -XPOST -H "X-Pact-Mock-Service: true" http://localhost/pact -d '{"consumer" : {"name": "Consumer Name"}, "provider": {"name": "Provider Name"}}' it doesn't blow up as I expected. What does it do for you @iamleeg?

@mefellows
Copy link
Member

I'll add the option in here too, marking as enhancement.

Adding it to the docker container makes sense also.

Copy link
Member

@mefellows mefellows left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you fix the issues and have a green build, we can bring this in.

src/pact.js Outdated
@@ -71,7 +71,7 @@ module.exports = (opts) => {

logger.info(`Setting up Pact with Consumer "${consumer}" and Provider "${provider}" using mock service on Port: "${port}"`)

const mockService = new MockService(consumer, provider, port, host, ssl, pactfileWriteMode)
const mockService = new MockService(consumer, provider, dir, port, host, ssl, pactfileWriteMode)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is probably the cause of the failing build. You're passing it as the third argument, but in the MockService constructor it's the 6th.

@bethesque
Copy link
Member

@mefellows I'm looking at removing the ability to set the location as per pact-foundation/pact-mock_service#74

@bethesque
Copy link
Member

I'd recommend NOT merging this PR - we will set the location in the docker image. However... I can't reproduce this problem with the docker image, so I'm very confused.

@bethesque bethesque self-assigned this Aug 21, 2017
@coveralls
Copy link

coveralls commented Aug 24, 2017

Coverage Status

Coverage remained the same at 95.699% when pulling aa66211 on iamleeg:post_pact_dir into 099b268 on pact-foundation:master.

@iamleeg
Copy link
Author

iamleeg commented Aug 24, 2017

@bethesque I also don't see that command failing. I don't know then what the difference between that request and the one I saw in the interaction with pact-js that I originally reported was, but will try to find out.

@iamleeg
Copy link
Author

iamleeg commented Aug 24, 2017

I've reapplied my stash from the last time I was working on this, and now have a different failure earlier in the flow, so can't replicate this problem with the setup I was trying to use. I'm not sure what changed, I was still using pact-js 2.6.0 (and have also tried with 2.7.0 with no change).

Unfortunately the new problem doesn't come with any logging beyond

[2017-08-24T12:19:34.496Z]  WARN: pact-node@4.12.0/29 on acb6a952e5dc: Like a Boss, you used a port outside of the recommended range (1024 to 49151); I too like to live dangerously.

so I have yet to dig into that.

@iamleeg
Copy link
Author

iamleeg commented Aug 24, 2017

That problem was that I wasn't clearing out interactions between runs, so I can reproduce my original problem. I'm using pact-js 2.7.0 at the moment. What I see:

  • I use const provider = pact({host: 'my-docker-image', port: 80, spec: 2, dir: '/tmp/pacts', log: '/tmp/logs/mock-service.log', consumer: 'client service', provider: 'provider service'}) to create the pact provider from pact-js

  • then call provider.removeInteractions()

  • then provider.addInteraction() once with a description of the expected request and response

  • at the moment, to isolate the problem to the pact mock, I'm not using my client code; I'm sending the same request in my test directly using axios.post

  • I call 'provider.verify()`, which succeeds

  • I call provider.finalize(), which fails. Here's the error message:

    {"message":"Error ocurred in mock service: Pact::ConsumerContractWriterError - Please indicate the directory to write the pact to by specifying the pact_dir field","backtrace":["/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer_contract/consumer_contract_writer.rb:137:in pact_dir'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer_contract/consumer_contract_writer.rb:132:in pactfile_path'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer_contract/consumer_contract_writer.rb:150:in log_message'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer_contract/consumer_contract_writer.rb:56:in update_pactfile'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer_contract/consumer_contract_writer.rb:52:in update_pactfile_if_needed'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer_contract/consumer_contract_writer.rb:37:in write'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/mock_service/request_handlers/pact_post.rb:31:in respond'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/mock_service/request_handlers/base_request_handler.rb:17:in call'","/usr/local/bundle/gems/rack-2.0.3/lib/rack/cascade.rb:33:in block in call'","/usr/local/bundle/gems/rack-2.0.3/lib/rack/cascade.rb:24:in each'","/usr/local/bundle/gems/rack-2.0.3/lib/rack/cascade.rb:24:in call'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer/mock_service/cors_origin_header_middleware.rb:11:in call'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer/mock_service/error_handler.rb:13:in call'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/mock_service/app.rb:32:in call'","/usr/local/bundle/gems/pact-mock_service-2.1.0/lib/pact/consumer/mock_service/set_location.rb:14:in call'","/usr/local/bundle/gems/rack-2.0.3/lib/rack/handler/webrick.rb:86:in service'","/usr/local/bundle/gems/webrick-1.3.1/lib/webrick/httpserver.rb:138:in service'","/usr/local/bundle/gems/webrick-1.3.1/lib/webrick/httpserver.rb:94:in run'","/usr/local/bundle/gems/webrick-1.3.1/lib/webrick/server.rb:191:in `block in start_thread'"]}

Looking at mockService.js, the failing call is a POST to http://host:port/pact with the body:

{
  consumer: { name: 'client service' },
  provider: { name: 'provider service' },
  pactfile_write_mode: 'overwrite'

}

If I send that body to the docker image after running docker-compose up in the repo, then it still doesn't blow up for me. :-/

@bethesque
Copy link
Member

I've replicated the issue now - for some reason I needed to go through the full process of setting up an interaction to expose the issue. I've pushed a new docker image with the pact dir already set, so you should have no problems now.

@iamleeg
Copy link
Author

iamleeg commented Aug 25, 2017

Thanks @bethesque!

@iamleeg iamleeg deleted the post_pact_dir branch August 25, 2017 09:06
@iamleeg
Copy link
Author

iamleeg commented Sep 6, 2017

Hi @bethesque, sorry it took me a long time to clear the decks to test this again. I have updated my image with

$ docker pull pactfoundation/pact-mock-service
Using default tag: latest
latest: Pulling from pactfoundation/pact-mock-service
90f4dba627d6: Already exists 
98c1a7514ba6: Pull complete 
b1391ef05ae4: Pull complete 
b37829f7707c: Pull complete 
ef10efd8fd30: Pull complete 
1a5d34396559: Pull complete 
5e7a63873a5a: Pull complete 
b2d0cf0085a5: Pull complete 
Digest: sha256:ddaeb4955f6028e788291275050d21dfad8e37b1499c8312884e9e1b72aba9cc
Status: Downloaded newer image for pactfoundation/pact-mock-service:latest

and the behaviour has not changed.

@bethesque
Copy link
Member

I can't reproduce the problem with the latest image. Can you clone https://github.com/pact-foundation/pact-mock-service-docker and run scripts/consumer-create-pact.sh against your latest (which appears to be the same as mine, 9cc)

$ docker pull pactfoundation/pact-mock-service
Using default tag: latest
latest: Pulling from pactfoundation/pact-mock-service
90f4dba627d6: Already exists
98c1a7514ba6: Already exists
b1391ef05ae4: Pull complete
b37829f7707c: Pull complete
ef10efd8fd30: Pull complete
1a5d34396559: Pull complete
5e7a63873a5a: Pull complete
b2d0cf0085a5: Pull complete
Digest: sha256:ddaeb4955f6028e788291275050d21dfad8e37b1499c8312884e9e1b72aba9cc
Status: Downloaded newer image for pactfoundation/pact-mock-service:latest
pact-mock-service-docker $ docker-compose up
Recreating pactmockservicedocker_pact-mock-service_1 ...
Recreating pactmockservicedocker_pact-mock-service_1 ... done
Attaching to pactmockservicedocker_pact-mock-service_1
pact-mock-service_1  | [2017-09-06 11:00:11] INFO  WEBrick 1.3.1
pact-mock-service_1  | [2017-09-06 11:00:11] INFO  ruby 2.4.1 (2017-03-22) [x86_64-linux-musl]
pact-mock-service_1  | [2017-09-06 11:00:11] INFO  WEBrick::HTTPServer#start: pid=6 port=80
$ scripts/consumer-create-pact.sh
Deleted interactions
Set interactions
{"message":"Hello world"}
Interactions matched
{
  "consumer": {
    "name": "Foo"
  },
  "provider": {
    "name": "Bar"
  },
  "interactions": [
    {
      "description": "foo",
      "request": {
        "method": "GET",
        "path": "/foo"
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json"
        },
        "body": {
          "message": "Hello world"
        }
      }
    }
  ],
  "metadata": {
    "pactSpecification": {
      "version": "1.0.0"
    }
  }
}

Can you see if you can modify scripts/consumer-create-pact.sh to recreate the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants