-
-
Notifications
You must be signed in to change notification settings - Fork 178
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into feat/post-verification-webhooks
# Conflicts: # tasks/database.rb
- Loading branch information
Showing
65 changed files
with
1,293 additions
and
374 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,28 +6,34 @@ | |
[![Issue Count](https://codeclimate.com/github/pact-foundation/pact_broker/badges/issue_count.svg)](https://codeclimate.com/github/pact-foundation/pact_broker) | ||
[![Dependency Status](https://gemnasium.com/badges/github.com/pact-foundation/pact_broker.svg)](https://gemnasium.com/github.com/pact-foundation/pact_broker) | ||
|
||
The Pact Broker provides a repository for consumer driven contracts created using the pact gem. | ||
The Pact Broker is an application for sharing for consumer driven contracts. It is optimised for use with "pacts" (contracts created by the [Pact][pact-docs] framework), but can be used for any type of contract that can be serialized to JSON. | ||
|
||
|
||
It: | ||
|
||
* solves the problem of how to share pacts between consumer and provider projects | ||
* allows you to [decouple your service release cycles][decouple] | ||
* provides API documentation that is guaranteed to be up-to date | ||
* allows you to release customer value quickly and confidently by [deploying your services independently][decouple] and avoiding the bottleneck of integration tests | ||
* solves the problem of how to share contracts and verification results between consumer and provider projects | ||
* tells you which versions of your applications can be deployed safely together | ||
* automatically versions your contracts | ||
* allows you to ensure backwards compatibility between multiple consumer and provider versions (eg. in a mobile or multi-tenant environment) | ||
* provides API documentation of your applications that is guaranteed to be up-to date | ||
* shows you real examples of how your services interact | ||
* allows you to visualise the relationships between your services | ||
|
||
Features: | ||
|
||
* A RESTful API for publishing and retrieving pacts. | ||
* An embedded HAL browser for navigating the API. | ||
* An embedded API browser for navigating the API. | ||
* Autogenerated documentation for each pact. | ||
* Dynamically generated network diagrams so you can visualise your microservice network. | ||
* Displays provider verificaton results so you know if you can deploy safely. | ||
* Provides a "matrix" of compatible consumer and provider versions, so you know which versions can be safely deployed together. | ||
* Provides badges to display pact verification statuses in your READMEs. | ||
* Enables a pact version to be tagged (ie. "prod") so a provider can verify itself against a fixed version of a pact to ensure backwards compatibility. | ||
* Provides webhooks to trigger a provider build when a consumer publishes a change to a pact. | ||
* Enables an application version to be tagged (ie. "prod", "feat/customer-preferences") to allow repository-like workflows. | ||
* Provides webhooks to trigger actions when pacts change eg. run provider build, notify a Slack channel. | ||
* View diffs between Pact versions so you can tell what expectations have changed. | ||
* [Docker Pact Broker][docker] | ||
* A [CLI][cli] for encorporating the Pact workflow into your continuous integration process. | ||
|
||
### How would I use the Pact Broker? | ||
|
||
|
@@ -42,10 +48,17 @@ Features: | |
1. The provider has a verification task that is configured with the URL to retrieve the latest pact between itself and the consumer. eg `http://my-pact-broker/pacts/provider/Animal%20Service/consumer/Zoo%20App/latest`. | ||
2. The provider build runs the pact verification task, which retrieves the pact from the Pact Broker, replays each request against the provider, and checks that the responses match the expected responses. | ||
3. If the pact verification fails, the build fails. The [Pact Broker CI Nerf Gun][nerf] magically determines who caused the verification to fail, and shoots them. | ||
4. The results of the verification are published back to the Pact Broker by the pact verification tool, so the consumer team will know if the code they have written will work IRL. | ||
4. The results of the verification are published back to the Pact Broker by the pact verification tool, so the consumer team will know if the code they have written will work in real life. | ||
|
||
If you don't have a [Pact Broker CI Nerf Gun][nerf], you'll probably want to read about using pact when the consumer and provider are being written by [different teams][different-teams]. | ||
|
||
#### Step 3. Back to the Consumer CI build | ||
|
||
The following funcationality is in beta release. Your feedback would be appreciated. | ||
|
||
1. The Consumer CI determines if the pact has been verified by running `pact-broker can-i-deploy --pacticipant CONSUMER_NAME --version CONSUMER_VERSION ...` (see documentation [here](https://github.com/pact-foundation/pact_broker-client#can-i-deploy)) | ||
1. If the pact has been verified, the deployment can proceed. | ||
|
||
## Documentation | ||
|
||
See the [wiki][wiki] for documentation on the Pact Broker. | ||
|
@@ -98,13 +111,14 @@ Use the HAL browser to view documentation as you browse. | |
* unix users just use your package manager | ||
* Run `git clone [email protected]:pact-foundation/pact_broker.git && cd pact_broker/example` | ||
* Run `bundle install` | ||
* Run `bundle exec rackup -p 8080` | ||
* Run `bundle exec rackup -p 8080` (this will use a Sqlite database. If you want to try it out with a Postgres database, see the [README](https://github.com/pact-foundation/pact_broker/tree/master/example) in the example directory.) | ||
* Open [http://localhost:8080](http://localhost:8080) and you should see a list containing the pact between the Zoo App and the Animal Service. | ||
* Click on the arrow to see the generated HTML documentation. | ||
* Click on either service to see an autogenerated network diagram. | ||
* Click on the HAL Browser link to have a poke around the API. | ||
* Click on the book icon under "docs" to view documentation related to a given relation. | ||
|
||
|
||
### For reals | ||
|
||
#### Hosted | ||
|
@@ -113,17 +127,20 @@ In a hurry? Hate having to run your own infrastructure? Check out the [Hosted Pa | |
|
||
#### Container solutions | ||
|
||
You can use the [Pact Broker Docker container][docker] or [Terraform on AWS][terraform] | ||
You can use the [Pact Broker Docker image][docker] or [Terraform on AWS][terraform] | ||
|
||
#### Rolling your own | ||
|
||
* Are you sure you don't just want to use the [Pact Broker Docker image][docker]? No Docker at your company yet? Ah well, keep reading. | ||
* Create a PostgreSQL (recommended) or MySQL (not recommended, see following note) database. | ||
* __Note:__ It is recommended to use __PostgreSQL__ as it will support JSON search features that are planned in the future, however MySQL the other [semi supported](https://github.com/pact-foundation/pact_broker/issues/33) database. | ||
* Install ruby 2.2.0 or later and bundler >= 1.12.0 | ||
* Copy the [example](/example) directory to the location you want to install the application. | ||
* __Note:__ It is recommended to use __PostgreSQL__ as it will support JSON search features that are planned in the future, however MySQL the other [semi supported](https://github.com/pact-foundation/pact_broker/issues/33) database. | ||
* Check the [travis.yml][travisyml] file to make sure you're using the version of the database that we're currently running our tests against. | ||
* If you're using PostgreSQL (did we mention this was _recommended!_) you'll find the database creation script in the [example/config.ru](https://github.com/pact-foundation/pact_broker/blob/master/example/config.ru). | ||
* Install ruby 2.2.0 or later and bundler >= 1.12.0 (if you've come this far, I'm assuming you know how to do both of these. Did I mention there was a [Docker][docker] image?) | ||
* Copy the [pact\_broker](https://github.com/DiUS/pact_broker-docker/tree/master/pact_broker) directory from the Pact Broker Docker project. This will have the recommended settings for database connections, logging, basic auth etc. Note that the Docker image uses Phusion Passenger as the web application server in front of the Pact Broker Ruby application, which is the recommended set up. | ||
* Modify the config.ru and Gemfile as desired (eg. choose database driver gem, set your database credentials. Use the "pg" gem if using Postgres and the "mysql2" gem if using MySQL) | ||
* Please ensure you use `encoding: 'utf8'` in your Sequel options to avoid encoding issues. | ||
* For production usage, use a web application server like [Phusion Passenger](https://www.phusionpassenger.com) or [Nginx](http://nginx.org/) to serve the Pact Broker application. | ||
* For production usage, use a web application server like [Phusion Passenger](https://www.phusionpassenger.com) or [Nginx](http://nginx.org/) to serve the Pact Broker application. You'll need to read up on the documentation for these yourself as it is beyond the scope of this documentation. | ||
* Deploy to your location of choice. | ||
|
||
## Upgrading | ||
|
@@ -142,3 +159,6 @@ Please read the [UPGRADING.md](UPGRADING.md) documentation before upgrading your | |
[twitter]: https://twitter.com/pact_up | ||
[gitter]: https://gitter.im/realestate-com-au/pact | ||
[issues]: https://github.com/pact-foundation/pact_broker/issues | ||
[pact-docs]: http://docs.pact.io | ||
[cli]: https://github.com/pact-foundation/pact-ruby-standalone/releases | ||
[travisyml]: https://github.com/pact-foundation/pact_broker/blob/master/.travis.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,103 +1,30 @@ | ||
require 'set' | ||
require 'openssl' | ||
require 'uri' | ||
require 'net/http' | ||
|
||
class Link | ||
def initialize from, to | ||
@from = from | ||
@to = to | ||
end | ||
uri = URI('https://self-signed.badssl.com') | ||
downloaded_cert_path = '/tmp/downloaded_cert.pem' | ||
|
||
def include? endpoint | ||
@from == endpoint || @to == endpoint | ||
end | ||
puts `openssl s_client -showcerts -servername #{uri.host} -connect #{uri.host}:#{uri.port} </dev/null 2>/dev/null|openssl x509 -text` | ||
command = "openssl s_client -showcerts -servername #{uri.host} -connect #{uri.host}:#{uri.port} </dev/null 2>/dev/null|openssl x509 -outform PEM > #{downloaded_cert_path}" | ||
puts command | ||
puts `#{command}` | ||
|
||
def connected? other | ||
(self.to_a & other.to_a).any? | ||
end | ||
|
||
def to_s | ||
"#{@from} - #{@to}" | ||
end | ||
cert_store = OpenSSL::X509::Store.new | ||
puts "Adding certificate #{downloaded_cert_path}" | ||
cert_store.add_file(downloaded_cert_path) | ||
|
||
def to_a | ||
[@from, @to] | ||
end | ||
req = Net::HTTP::Get.new(uri) | ||
|
||
end | ||
|
||
def unique_nodes links | ||
links.collect(&:to_a).flatten.uniq.sort | ||
end | ||
|
||
def nodes_connected_to_node node, links | ||
unique_nodes links.select{|l|l.include?(node)} | ||
end | ||
|
||
def connected_links link, link_pool | ||
link_pool.select{|l| l.connected?(link)} | ||
end | ||
|
||
def nodes_connected_to_nodes_within_pool nodes, links, node_pool | ||
nodes.collect{ | node | nodes_connected_to_node(node, links) }.flatten & node_pool | ||
end | ||
|
||
def connected_links_still_within_pool links, link_pool | ||
links.collect{ | link | connected_links(link, link_pool) }.flatten.uniq | ||
end | ||
|
||
def split_into_clusters_of_nodes links | ||
node_pool = unique_nodes links | ||
groups = [] | ||
|
||
while node_pool.any? | ||
group = [] | ||
groups << group | ||
connected_nodes = [node_pool.first] | ||
|
||
while connected_nodes.any? | ||
group.concat(connected_nodes) | ||
node_pool = node_pool - connected_nodes | ||
connected_nodes = nodes_connected_to_nodes_within_pool connected_nodes, links, node_pool | ||
end | ||
end | ||
options = { | ||
:use_ssl => uri.scheme == 'https', | ||
verify_mode: OpenSSL::SSL::VERIFY_PEER, | ||
cert_store: cert_store | ||
} | ||
|
||
groups | ||
response = Net::HTTP.start(uri.hostname, uri.port, options) do |http| | ||
http.request req | ||
end | ||
|
||
def recurse link, link_pool | ||
connected_links = link_pool.select{ | candidate| candidate.connected?(link) } | ||
if connected_links.empty? | ||
[link] | ||
else | ||
([link] + connected_links.map{| connected_link| recurse(connected_link, link_pool - connected_links)}.flatten).uniq | ||
end | ||
end | ||
|
||
def recurse_groups groups, link_pool | ||
if link_pool.empty? | ||
groups | ||
else | ||
first, *rest = *link_pool | ||
group = recurse first, rest | ||
recurse_groups(groups + [group], link_pool - group) | ||
end | ||
end | ||
|
||
def split_into_clusters_of_links links | ||
recurse_groups [], links.dup | ||
end | ||
|
||
links = [Link.new('A', 'B'), Link.new('A', 'C'), Link.new('C', 'D'), Link.new('D', 'E'), Link.new('E','A'), | ||
Link.new('Y', 'Z'), Link.new('X', 'Y'), | ||
Link.new('M', 'N'), Link.new('N', 'O'), Link.new('O', 'P'), Link.new('P','Q')] | ||
|
||
|
||
groups = split_into_clusters_of_nodes links | ||
|
||
puts groups.collect{ | group| "group = #{group.join(" ")}"} | ||
|
||
groups = split_into_clusters_of_links links | ||
puts groups.collect{ | group| "group = #{group.join(", ")}"} | ||
|
||
|
||
|
||
|
||
puts response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
require_relative 'migration_helper' | ||
|
||
Sequel.migration do | ||
change do | ||
create_table(:certificates, charset: 'utf8') do | ||
primary_key :id | ||
String :uuid, null: false, unique: true, unique_constraint_name: 'uq_certificate_uuid' | ||
String :description, null: true | ||
String :content, null: false, type: PactBroker::MigrationHelper.large_text_type | ||
DateTime :created_at, null: false | ||
DateTime :updated_at, null: false | ||
end | ||
end | ||
end |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.