Skip to content

Commit

Permalink
feat(daemonless): initial wip to install deps
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Mar 14, 2018
1 parent 35dc302 commit a9690a4
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 92 deletions.
45 changes: 25 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ including [flexible matching](http://docs.pact.io/documentation/matching.html).
- [Introduction](#introduction)
- [Table of Contents](#table-of-contents)
- [Installation](#installation)
- [Installation on *nix](#installation-on-nix)
- [Running](#running)
- [Consumer](#consumer)
- [Matching (Consumer Tests)](#matching-consumer-tests)
Expand All @@ -62,27 +63,34 @@ including [flexible matching](http://docs.pact.io/documentation/matching.html).

## Installation

* Download one of the zipped [release](https://github.com/pact-foundation/pact-go/releases) distributions for your OS.
* Unzip the package into a known location, and ensuring the `pact-go` binary is on the `PATH`, next to the `pact` folder.
* Run `pact-go` to see what options are available.
* Run `go get -d github.com/pact-foundation/pact-go` to install the source packages
1. Download the [latest release](https://github.com/pact-foundation/pact-ruby-standalone/releases) of the standalone tools and ensure the binaries are on your `PATH`:
1. Unzip the package into a known location, and ensuring the `pact-go` binary is on the `PATH`.
1. Run `go get -d github.com/pact-foundation/pact-go` to install the source packages

## Running
See below for how to automate this:

Pact Go runs a two-step process:
### Installation on *nix

1. Run `pact-go daemon` in a separate process/shell. The Consumer and Provider
DSLs communicate over a local (RPC) connection, and is transparent to clients.
1. Create your Pact Consumer/Provider Tests. It defaults to run on port `6666`.
```sh
cd /opt
curl -fsSL https://raw.githubusercontent.com/pact-foundation/pact-ruby-standalone/master/install.sh | bash
export PATH=$PATH:/opt/pact/bin
go get -d github.com/pact-foundation/pact-go
```

*NOTE: The daemon is thread safe and it is normal to leave it
running for long periods (e.g. on a CI server).*
Test the installation:
```sh
pact help
```

## Running

Pact Go runs as part of your regular Go tests!

### Consumer

We'll run through a simple example to get an understanding the concepts:

1. Start the daemon with `./pact-go daemon`.
1. `go get github.com/pact-foundation/pact-go`
1. `cd $GOPATH/src/github.com/pact-foundation/pact-go/examples/`
1. `go test -v -run TestConsumer`.
Expand Down Expand Up @@ -110,7 +118,6 @@ func TestConsumer(t *testing.T) {

// Create Pact connecting to local Daemon
pact := &dsl.Pact{
Port: 6666, // Ensure this port matches the daemon port!
Consumer: "MyConsumer",
Provider: "MyProvider",
Host: "localhost",
Expand Down Expand Up @@ -227,7 +234,6 @@ Read more about [flexible matching](https://github.com/realestate-com-au/pact/wi

### Provider

1. Start the daemon with `./pact-go daemon`.
1. `go get github.com/pact-foundation/pact-go`
1. `cd $GOPATH/src/github.com/pact-foundation/pact-go/examples/`
1. `go test -v -run TestProvider`.
Expand All @@ -237,7 +243,7 @@ Here is the Provider test process broker down:
1. Start your Provider API:

You need to be able to first start your API in the background as part of your tests
before you can run the verification process. Here we create `startServer` which can be
before you can run the verification process. Here we create `startServer` which can be
started in its own goroutine:

```go
Expand Down Expand Up @@ -272,7 +278,7 @@ Here is the Provider test process broker down:
```

Note that the server has a `/setup` endpoint that is given a `types.ProviderState` and allows the
verifier to setup any
verifier to setup any
[provider states](http://docs.pact.io/documentation/provider_states.html) before
each test is run.

Expand All @@ -286,7 +292,6 @@ Here is the Provider test process broker down:
// Create Pact connecting to local Daemon
pact := &dsl.Pact{
Port: 6666, // Ensure this port matches the daemon port!
Consumer: "MyConsumer",
Provider: "MyProvider",
}
Expand Down Expand Up @@ -322,7 +327,7 @@ When validating a Provider, you have 3 options to provide the Pact files:
```go
pact.VerifyProvider(t, types.VerifyRequest{
ProviderBaseURL: "http://myproviderhost",
PactURLs: []string{"http://broker/pacts/provider/them/consumer/me/latest/dev"},
PactURLs: []string{"http://broker/pacts/provider/them/consumer/me/latest/dev"},
ProviderStatesSetupURL: "http://myproviderhost/setup",
BrokerUsername: os.Getenv("PACT_BROKER_USERNAME"),
BrokerPassword: os.Getenv("PACT_BROKER_PASSWORD"),
Expand All @@ -333,7 +338,7 @@ When validating a Provider, you have 3 options to provide the Pact files:
```go
pact.VerifyProvider(t, types.VerifyRequest{
ProviderBaseURL: "http://myproviderhost",
BrokerURL: "http://brokerHost",
BrokerURL: "http://brokerHost",
ProviderStatesSetupURL: "http://myproviderhost/setup",
BrokerUsername: os.Getenv("PACT_BROKER_USERNAME"),
BrokerPassword: os.Getenv("PACT_BROKER_PASSWORD"),
Expand All @@ -345,7 +350,7 @@ When validating a Provider, you have 3 options to provide the Pact files:
pact.VerifyProvider(t, types.VerifyRequest{
ProviderBaseURL: "http://myproviderhost",
BrokerURL: "http://brokerHost",
Tags: []string{"latest", "sit4"},
Tags: []string{"latest", "sit4"},
ProviderStatesSetupURL: "http://myproviderhost/setup",
BrokerUsername: os.Getenv("PACT_BROKER_USERNAME"),
BrokerPassword: os.Getenv("PACT_BROKER_PASSWORD"),
Expand Down
33 changes: 0 additions & 33 deletions command/daemon.go

This file was deleted.

38 changes: 0 additions & 38 deletions command/daemon_test.go

This file was deleted.

27 changes: 27 additions & 0 deletions command/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package command

import (
"fmt"

"github.com/spf13/cobra"
)

var path string
var installCmd = &cobra.Command{
Use: "install",
Short: "Install required tools",
Long: "Installs underlying Pact standalone tools for use by the library",
Run: func(cmd *cobra.Command, args []string) {
setLogLevel(verbose, logLevel)

// Run the installer
fmt.Println("[INFO] Installing required tools...", path)
fmt.Println("[INFO] Checking installation succeeded...")
fmt.Println("[INFO] Tooling installed and up to date!")
},
}

func init() {
installCmd.Flags().StringVarP(&path, "path", "p", "/opt/pact", "Local daemon port to listen on")
RootCmd.AddCommand(installCmd)
}
15 changes: 15 additions & 0 deletions command/install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package command

import (
"os"
"testing"
)

func TestInstallCommand(t *testing.T) {
os.Args = []string{"install"}
err := installCmd.Execute()
if err != nil {
t.Fatalf("Error: %v", err)
}
installCmd.Run(nil, os.Args)
}
2 changes: 1 addition & 1 deletion command/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
)

func Test_VersionCommand(t *testing.T) {
func TestVersionCommand(t *testing.T) {
os.Args = []string{"version"}
err := versionCmd.Execute()
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions install/install_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package install

var defaultPath = "c:/bin"
3 changes: 3 additions & 0 deletions install/install_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package install

var defaultPath = "c:/bin"
3 changes: 3 additions & 0 deletions install/install_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package install

var defaultPath = "/opt"
90 changes: 90 additions & 0 deletions install/installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Package install contains functions necessary for installing and checking
// if the necessary underlying Ruby tools have been properly installed
package install

import (
"fmt"
"log"
"os/exec"
"strings"

goversion "github.com/hashicorp/go-version"
)

// Installer manages the underlying Ruby installation
type Installer struct {
}

const (
mockServiceRange = ">= 2.6.4, < 3.0.0"
verifierRange = ">= 1.11.0, < 2.0.0"
brokerRange = ">= 1.14.0, < 2.0.0"
)

var versionMap = map[string]string{
"pact-mock-service": mockServiceRange,
"pact-provider-verifier": verifierRange,
"pact-broker": brokerRange,
}

// CheckInstallation checks installation of all of the tools
func (i *Installer) CheckInstallation() error {

for binary, versionRange := range versionMap {
log.Println("[INFO] checking", binary, "within range", versionRange)

version, err := i.GetVersionForBinary(binary)
if err != nil {
return err
}

if err = i.CheckVersion(binary, version); err != nil {
return err
}
}

return nil
}

// CheckVersion checks installation of a given binary using semver-compatible
// comparisions
func (i *Installer) CheckVersion(binary, version string) error {
log.Println("[DEBUG] checking version for binary", binary, "version", version)
v, err := goversion.NewVersion(version)
if err != nil {
log.Println("[DEBUG] err", err)
return err
}

versionRange, ok := versionMap[binary]
if !ok {
return fmt.Errorf("unable to find version range for binary %s", binary)
}

log.Println("[DEBUG] checking if version", v, "within semver range", versionRange)
constraints, err := goversion.NewConstraint(versionRange)
if constraints.Check(v) {
log.Println("[DEBUG]", v, "satisfies constraints", v, constraints)
return nil
}

return fmt.Errorf("version %s does not match constraint %s", version, versionRange)
}

// InstallTools installs the CLI tools onto the host system
func (i *Installer) InstallTools() error {
log.Println("[INFO] Installing tools")

return nil
}

// GetVersionForBinary gets the version of a given Ruby binary
func (i *Installer) GetVersionForBinary(binary string) (version string, err error) {
log.Println("[DEBUG] running binary", binary)

cmd := exec.Command(binary, "version")
content, err := cmd.Output()
version = string(content)

return strings.TrimSpace(version), err
}
44 changes: 44 additions & 0 deletions install/installer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package install

import (
"fmt"
"testing"
)

func TestInstaller_CheckVersion(t *testing.T) {
i := Installer{}
err := i.CheckVersion("pact-mock-service", "2.7.3")

if err != nil {
t.Fatal("error:", err)
}
}

func TestInstaller_CheckVersionFail(t *testing.T) {
i := Installer{}
err := i.CheckVersion("pact-mock-service", "3.7.3")

if err == nil {
t.Fatal("want error, got none")
}
}

func TestInstaller_getVersionForBinary(t *testing.T) {
i := Installer{}
v, err := i.GetVersionForBinary("pact-mock-service")

if err != nil {
t.Fatal("error:", err)
}

fmt.Println("version: ", v)
}

func TestInstaller_CheckInstallation(t *testing.T) {
i := Installer{}
err := i.CheckInstallation()

if err != nil {
t.Fatal("error:", err)
}
}

0 comments on commit a9690a4

Please sign in to comment.