diff --git a/Gopkg.lock b/Gopkg.lock index 1b0c8ed7b..7efb9fdb8 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,125 +3,116 @@ [[projects]] branch = "master" + digest = "1:36fe9527deed01d2a317617e59304eb2c4ce9f8a24115bcc5c2e37b3aee5bae4" name = "github.com/gin-contrib/sse" packages = ["."] + pruneopts = "UT" revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae" [[projects]] + digest = "1:489e108f21464371ebf9cb5c30b1eceb07c6dd772dff073919267493dd9d04ea" name = "github.com/gin-gonic/gin" packages = [ ".", "binding", - "render" + "render", ] + pruneopts = "UT" revision = "d459835d2b077e44f7c9b453505ee29881d5d12d" version = "v1.2" [[projects]] - name = "github.com/go-kit/kit" - packages = [ - "endpoint", - "log", - "transport/http" - ] - revision = "ca4112baa34cb55091301bdc13b1420a122b1b9e" - version = "v0.7.0" - -[[projects]] - name = "github.com/go-logfmt/logfmt" - packages = ["."] - revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" - version = "v0.3.0" - -[[projects]] - name = "github.com/go-stack/stack" - packages = ["."] - revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" - version = "v1.7.0" - -[[projects]] + digest = "1:15042ad3498153684d09f393bbaec6b216c8eec6d61f63dff711de7d64ed8861" name = "github.com/golang/protobuf" packages = ["proto"] + pruneopts = "UT" revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" version = "v1.1.0" -[[projects]] - name = "github.com/gorilla/context" - packages = ["."] - revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" - version = "v1.1.1" - -[[projects]] - name = "github.com/gorilla/mux" - packages = ["."] - revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" - version = "v1.6.2" - [[projects]] branch = "master" + digest = "1:e12b92b8bb20af6e299e9829534cfe790857702a988d3f0443e772c9d82a4fd2" name = "github.com/hashicorp/go-version" packages = ["."] + pruneopts = "UT" revision = "23480c0665776210b5fbbac6eaaee40e3e6a96b7" [[projects]] branch = "master" + digest = "1:ce3f7860fd68bd2dd4c3735e2aed8c9de7c7d05bd6ad7d97a6bedcf4fe7b84fb" name = "github.com/hashicorp/logutils" packages = ["."] + pruneopts = "UT" revision = "0dc08b1671f34c4250ce212759ebd880f743d883" [[projects]] + digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] + pruneopts = "UT" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] - branch = "master" - name = "github.com/kr/logfmt" - packages = ["."] - revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" - -[[projects]] + digest = "1:d4d17353dbd05cb52a2a52b7fe1771883b682806f68db442b436294926bbfafb" name = "github.com/mattn/go-isatty" packages = ["."] + pruneopts = "UT" revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" version = "v0.0.3" [[projects]] + digest = "1:31f9d9941245e05e806636e3e77fd3bfb21e8668d7d03d47ea71c8ebda21dfec" name = "github.com/spf13/cobra" packages = ["."] + pruneopts = "UT" revision = "f447048345b64b3247b29a679a14bd0da12c7f2f" [[projects]] + digest = "1:00b1571a9044e9977c1e6ddd9a287058d6af85e4385b5fed1e70dea79527fd0c" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "UT" revision = "cb88ea77998c3f024757528e3305022ab50b43be" [[projects]] + digest = "1:03aa6e485e528acb119fb32901cf99582c380225fc7d5a02758e08b180cb56c3" name = "github.com/ugorji/go" packages = ["codec"] + pruneopts = "UT" revision = "b4c50a2b199d93b13dc15e78929cfb23bfdf21ab" version = "v1.1.1" [[projects]] + digest = "1:7bcd7406893de9d36236adc3ab85563c2ec30fcd97194b6a1835e798a65edf09" name = "golang.org/x/sys" packages = ["unix"] + pruneopts = "UT" revision = "076b546753157f758b316e59bcb51e6807c04057" [[projects]] + digest = "1:cbc72c4c4886a918d6ab4b95e347ffe259846260f99ebdd8a198c2331cf2b2e9" name = "gopkg.in/go-playground/validator.v8" packages = ["."] + pruneopts = "UT" revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf" version = "v8.18.2" [[projects]] + digest = "1:858458e1fcdb1cb44ded97c2ae2b610ee9336fdb0a8347ea1ad835e6a1db6c76" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "UT" revision = "a83829b6f1293c91addabc89d0571c246397bbf4" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "12ec2bff4745258b1c4a2e451de650f4fb0f74d32b3f03f17ef53b699c259a8c" + input-imports = [ + "github.com/gin-gonic/gin", + "github.com/hashicorp/go-version", + "github.com/hashicorp/logutils", + "github.com/spf13/cobra", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/README.md b/README.md index 05887f361..79fab4de6 100644 --- a/README.md +++ b/README.md @@ -382,7 +382,7 @@ _Important Note_: You should only use this feature for things that can not be pe For each _interaction_ in a pact file, the order of execution is as follows: -`BeforeEach` -> `StateHandler` -> `RequestFilter (pre)`, `Execute Provider Test` -> `RequestFilter (post)` -> `AfterEach` +`BeforeEach` -> `StateHandler` -> `RequestFilter (pre)` -> `Execute Provider Test` -> `RequestFilter (post)` -> `AfterEach` If any of the middleware or hooks fail, the tests will also fail. @@ -807,6 +807,27 @@ cd examples/message/provider PACT_DESCRIPTION="a user" PACT_PROVIDER_STATE="user with id 127 exists" go test -v . ``` +### Verifying APIs with a self-signed certificate + +Supply your own TLS configuration to customise the behaviour of the runtime: + +```go + _, err := pact.VerifyProvider(t, types.VerifyRequest{ + ProviderBaseURL: "https://localhost:8080", + PactURLs: []string{filepath.ToSlash(fmt.Sprintf("%s/consumer-selfsignedtls.json", pactDir))}, + CustomTLSConfig: &tls.Config{ + RootCAs: getCaCertPool(), // Specify a custom CA pool + // InsecureSkipVerify: true, // Disable SSL verification altogether + }, + }) +``` + +See [self-signed certificate](https://github.com/pact-foundation/pact-go/examles/customTls/self_signed_certificate_test.go) for an example. + +### Testing AWS API Gateway APIs + +AWS changed their certificate authority last year, and not all OSs have the latest CA chains. If you can't update to the latest certificate bunidles, see "Verifying APIs with a self-signed certificate" for how to work around this. + ## Contact Join us in slack: [![slack](http://slack.pact.io/badge.svg)](http://slack.pact.io) diff --git a/dsl/pact.go b/dsl/pact.go index 513a402f4..e57a36919 100644 --- a/dsl/pact.go +++ b/dsl/pact.go @@ -340,6 +340,7 @@ func (p *Pact) VerifyProviderRaw(request types.VerifyRequest) (types.ProviderVer TargetPath: u.Path, Middleware: m, InternalRequestPathPrefix: providerStatesSetupPath, + CustomTLSConfig: request.CustomTLSConfig, } // Starts the message wrapper API with hooks back to the state handlers @@ -459,7 +460,7 @@ func AfterEachMiddleware(AfterEach types.Hook) proxy.Middleware { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { next.ServeHTTP(w, r) - if r.URL.Path != "/__setup" { + if r.URL.Path != providerStatesSetupPath { log.Println("[DEBUG] executing after hook") err := AfterEach() diff --git a/examples/customTls/certs/ca.pem b/examples/customTls/certs/ca.pem new file mode 100644 index 000000000..0c5348a0d --- /dev/null +++ b/examples/customTls/certs/ca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDAjCCAeqgAwIBAgIRANd+eeBjb4D4mNW86NmUFk8wDQYJKoZIhvcNAQELBQAw +KjESMBAGA1UEChMJbG9jYWxob3N0MRQwEgYDVQQDEwtQa2kgQ0EgUm9vdDAeFw0x +NzAyMjgyMjIzMDBaFw0yMDAyMTMyMjIzMDBaMCoxEjAQBgNVBAoTCWxvY2FsaG9z +dDEUMBIGA1UEAxMLUGtpIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDS4qFc21Bh5fw4UftWS/MLxKkyJklX+045brxmYL05zGA/isF1QWSq +pZaXaXhFr68/LcXAHOAiNzJSHe9ezscnn7lLN0J+6v5wvW6UKoQhMdCZpWHsGFe5 +e4od6hWJm6rjh3qGx4ENgqXOZNukRMYbig7MKGE5htxcnvdImrPXAiRtuJ6Aa6bl +dBhkpOhQwHEey90NtcliRM6H1jYcCbhtlRStCVXsWiMjfpq9YIq+Wf/ece27Rvgy +DX3UVNkRTuS0ZeX+D3n4lyOMTzgT6Cn0OUU23D5TRCCkDCDxkXgmnT6Cri9x2WnX +AT7c2apUAx6ms9+AACE32ijqSg0Zx0+zAgMBAAGjIzAhMA4GA1UdDwEB/wQEAwIC +pDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCZ/d2+NWcU2bNy +/W4XrwOHuBGVWW6vB2HGDN8l+Ut3K6Gbc5sXrkmmoap2y9zZKZl9mybchqQUJ9Qo +U8zrhRJ5L74NRay9Jm+csRXbMBdSZtfJ8RRzZK7cr+fZ3DTd7tReSmV00nj7ciGj +O2s73/GZHab7FzbTSbEf/5ei0UMAlN4L89DxzJxfnvIg6wu7dXg/QPhU3Ws4Y4bj +5Dpl7pS2ZnVTh+cz39PgD+WkjubSx/CfOoo0bvwXKvg7vuE3HB65aP8tEZePSj4t +MKWLAxwTNSqq7FVDrYkpgsnG00BTefaViTRyEuMaBWc4IpJ+r+W2ODEtFTWVyiyJ +zXOYmm2Y +-----END CERTIFICATE----- diff --git a/examples/customTls/certs/cert-key.pem b/examples/customTls/certs/cert-key.pem new file mode 100644 index 000000000..f1bcc858d --- /dev/null +++ b/examples/customTls/certs/cert-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAuV2YLWXBXUyRp0FEIBr/Jp2EeOcm9XfQPZzZ6M21eH3Cky29 ++OD0ynINBdFHi7QB5fFdnTtg4jpH+q9CvvpGVcrW6tpjKic+RaN6abnSkz+RrXII +X4RtfV/W9wMz6V/h8nhzGWQID0iQkhooaIvTie2nQ+gwQm8wmCL1+KT2IRoELCvC +3VwrjDGde+dSOp+g9oWo4CkCce+wnSQQkI1Htctaq9EayAnrpPFupSTw0+AEOBJK +fGXg2yBN3EqUXBmF/jNcNsMqjV4LCheH6QYWSUxt24HoL9ycPdRnPeUKmzPi9dE9 +dNfXvPtoltE8e/D8zTNNGWcRgGR0lzfxuWeW/wIDAQABAoIBAEx13+Sx+W3bvKTq +FgjMOf0asl8QshBEyL/xaC1QVQ+LiGwfTSJQ4Ih1PQvuRH3K1ZGc2wmVSaRnd/Ne +wcB3CfYvgjFDve3QXC5rfX4I6WRVr2iFBhEoVeWGV+xyBMK6C0ByEMAjc/Oh8ghi +A9MEAlD9l6Y6K1Xr+XZ3zVAv81q5ZMEQsTERUkLA9lwDUpkQVipoLoKEVUeDiRvB +jH+t9/I+axyARyuEx0Vx4Dza4AOhyNdW9J9szlAo2dhV21vW12MLvKH9jx1U2iAw +vOBPe87xX40EIbiUkDrFKogdibFylQp/EWdsWFPM794b3D8/czfh2QYInghfoTzO +bk5+rrECgYEA8u5UBYHYhHV9cQNAZVmpDE1JwUBg34q5M11TuSs7dyy2iqiHI7MS +ysGsaOlf2bycKXQw10Ut+SVR0qnxjf2E/+cuCwnMySCaCPzat9UcGTMk3PqW7B4r +foYmUmgH9n9zc845/L/LNEtHkeLEAGOJL+jvwx4dKxf0C84TZmHUKscCgYEAw1Z4 +QI5L6OKIL1dGDUWLMJXkplxDSPH7XNwDg6zGa81T1NfgDCA+lyLqXEp9YqMSOk5N +4X+mTspazmgv3x6b6urGtIIRENZFLFgKqNfwDFkWDShwChF/8M7bzJsS4P/cNtr1 +lV0RHFERErRIE88v4ErXWwzDmOC/fJojJEW3OgkCgYEAzEuVKVR7C1nq9kFvxEvU +mF3e6sADN7rn6MRRhmVPCvf1Q0Ja87DC2vRo04l/bBLrmQj3kfHBqcayuuDkHS7Y +zIRT+kBxkarzHx/Vp8d2a9LQ621pwoPUvACA9cg6+hdQtlD1/xIkB4RPWeZEQrdy +RXI1P/dxPC5WtB7HvdADpz0CgYEApzvkgABTZPJsfXtOchZT8CikNPlQcacZ+Io0 +SAsnZSvI1bRsEHWaoHI4CwOLDWNnO5vGeYR7sYD09TmlonPmMN0HeYrRaYTIfAp0 +NdGJpkiu5Fz2buhEjLnM3AL3ysHCmwQitNmUyJVu9IB8JNmAt5nbfgwTeVMRHXAp +HejB0WECgYEA5hLQLsyqJY+BzzrvsC9RJ5y/U+P1KMFWnTyo/O8q2tihqSc9tlmk +Jun18bc6z9qzwiSrYqOpAsE6IJlG+Cf39tXytVCxpuBXIe529VZekl2tEYaqdiQ1 +0fbh7R+eGKRjtl+bXucciv+jok13oNWCTuTcpzbxWbNxenpMVYPwB5s= +-----END RSA PRIVATE KEY----- diff --git a/examples/customTls/certs/cert.pem b/examples/customTls/certs/cert.pem new file mode 100644 index 000000000..709cd29c2 --- /dev/null +++ b/examples/customTls/certs/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGzCCAgOgAwIBAgIRAP5kAANG+3/2fVhI4QOB3qQwDQYJKoZIhvcNAQELBQAw +KjESMBAGA1UEChMJbG9jYWxob3N0MRQwEgYDVQQDEwtQa2kgQ0EgUm9vdDAeFw0x +NzAyMjgyMjIzMDBaFw0yMDAyMTMyMjIzMDBaMBExDzANBgNVBAoTBmNsaWVudDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALldmC1lwV1MkadBRCAa/yad +hHjnJvV30D2c2ejNtXh9wpMtvfjg9MpyDQXRR4u0AeXxXZ07YOI6R/qvQr76RlXK +1uraYyonPkWjemm50pM/ka1yCF+EbX1f1vcDM+lf4fJ4cxlkCA9IkJIaKGiL04nt +p0PoMEJvMJgi9fik9iEaBCwrwt1cK4wxnXvnUjqfoPaFqOApAnHvsJ0kEJCNR7XL +WqvRGsgJ66TxbqUk8NPgBDgSSnxl4NsgTdxKlFwZhf4zXDbDKo1eCwoXh+kGFklM +bduB6C/cnD3UZz3lCpsz4vXRPXTX17z7aJbRPHvw/M0zTRlnEYBkdJc38blnlv8C +AwEAAaNVMFMwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkq +hkiG9w0BAQsFAAOCAQEASZe43Hi5HDj4odD7fjPHZcNOFUjc4GV5xR0P5sKS1yVO +3D5Gf9v4OVA7O3ejCLQP2lSq++EMUChAVpCJsfzXDwqe8YoHLnSS+EID+JpHEZ8P +PXXc59S/2HN7kEP447MRJCpFbOHy/axFkzZAlpQr7ffUhPQy3gnDWHDQ6uie6Od5 +bRX2B6Whgy9ey7PR3CMT8+SowCjhsKqE3y0vto+55XxMec35uKXI/djOZzje94fE +n7plsWLOgYu0aeOkVKLe6s/Q0/mjO7zicDHwMq0QvFIcMU/MgrZkvcq+2sg/6Rp0 +iKnKss7cdrxnA7fOsGK8mWP0U6GizCvVigI1zN5dZg== +-----END CERTIFICATE----- diff --git a/examples/customTls/certs/server-cert.pem b/examples/customTls/certs/server-cert.pem new file mode 100644 index 000000000..024eb2546 --- /dev/null +++ b/examples/customTls/certs/server-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDHTCCAgWgAwIBAgIQQcVnWwEK0r3ZCbXx+LQRtTANBgkqhkiG9w0BAQsFADAq +MRIwEAYDVQQKEwlsb2NhbGhvc3QxFDASBgNVBAMTC1BraSBDQSBSb290MB4XDTE3 +MDIyODIyMjMwMFoXDTIwMDIxMzIyMjMwMFowFDESMBAGA1UEChMJbG9jYWxob3N0 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOk54aC6EXZpNcxlO8L/ +ZIc/u4HNrB2VovT9osAs+ZPZOxd6w/l3e5mblxbh3j1Otjh5Y9e1wm9c0DytRhx9 +NUvzJ5weECGmk0FgU9Oe/OHnn5WayUK0Z8S56ln9bZbXDlnusRCyMGXhFuQqoabP +rpfqNvIP5XQeKxJMnLp2xYZV18O6nmjGYSSLMjNLr6MqA/KRRyP68yLhx4pXH1mL +bA5pjoxiJoI7tGLUTkMWco4O7bW0czR9AK72ZALSDgWDIKLQlRlQJ05wk+wnDykk +4pt6gABodkeyJvp6D5ayuAZBH0xOGxOW2Y4RPowb0tNIw4Sd7HthodLLjUiM7QwJ +AQIDAQABo1UwUzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIG +CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0G +CSqGSIb3DQEBCwUAA4IBAQB3DOgS/faqoMLqHCwTJsocD4etXU1Es7zTsI8QSYLp +JCj4ykJ58NASmfwtn+MDBc0wiKqP8Cyudh5j2uQGQ/pL/h99EGy4TY7rN/riop0m +x07yvV+mi65nwT/YEyX3Jymx4+78AvdHIWT9uj5nED6+pBufqHQHVm6btPF/hsA1 +4YTbWSGnrkcplBw3sWP5HoVVtfJ7TzhqVrSSQB+lRRXPHzRCq5f3BM5fZ7bMt3LI +9j8cXrSXSu53LZ/llTLGU5DbReAJPDQpSdwy56wMD/cXQXxt6blwZdLEneYQ8eqO +kD7eZDlUKz1Dhj7qoFnAhDU1ypxBF4A04E/qpPQHrkq1 +-----END CERTIFICATE----- diff --git a/examples/customTls/certs/server-key.pem b/examples/customTls/certs/server-key.pem new file mode 100644 index 000000000..7366917d5 --- /dev/null +++ b/examples/customTls/certs/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAwOk54aC6EXZpNcxlO8L/ZIc/u4HNrB2VovT9osAs+ZPZOxd6 +w/l3e5mblxbh3j1Otjh5Y9e1wm9c0DytRhx9NUvzJ5weECGmk0FgU9Oe/OHnn5Wa +yUK0Z8S56ln9bZbXDlnusRCyMGXhFuQqoabPrpfqNvIP5XQeKxJMnLp2xYZV18O6 +nmjGYSSLMjNLr6MqA/KRRyP68yLhx4pXH1mLbA5pjoxiJoI7tGLUTkMWco4O7bW0 +czR9AK72ZALSDgWDIKLQlRlQJ05wk+wnDykk4pt6gABodkeyJvp6D5ayuAZBH0xO +GxOW2Y4RPowb0tNIw4Sd7HthodLLjUiM7QwJAQIDAQABAoIBAG9edc7/ZkwsiyLG +5G6y7ZRQzIdosZ862SdhvofV4GEZbODDdllrTQJrNLruN+mAhU+HnPT6FHGyrud9 +EB+Y1OQO+8qTQ3vWoX8D0CO02WVu2bR0vw6P1uzNUvOrjjZVTcR4QOeyFt0ABAme +Icp/LgjCpTGhX3H9Lml5QAd/UpBHMuGYpZ7NZTRED4spWKYoQeqhCNzU7lYfW9W4 +xPdRbgBJ75daUPFCrCAU/hny+Iosl8Qc+dl9F+idtI4bvWw+ozKzgwhgicrYtYiQ +yuyR8DFD/hQ8Kl5Gzxmdkz97MZu2MffXiJaa7MelrAKV9L8plVmzPX3nNkphHjM5 +aCDDlUECgYEA82wrxpWwBLzgxSQGpN1wV3p29W8+tjp5XsTGQvHdFEPPLqAvl4oX +fZdLNSyiTI1lMbQ1zy6K9jQABIn4KEWKj6xNXXnj3tQsjJLbJBuC+2UaKJa2CG01 +jESTTLmjgBIGZneRxgYdFF5xyINnnaydhH0ijVXNIfrP2r4W4mqGRGkCgYEAyuDs +TKzgfNTbotJ4U4u44Y1TjmEknNggjNktOKPn6uwi5OITXMcdSzmQUPRvnX6Fm/Iy +6qF0XlG3eBFYxNWnWRLzE8xMFovnhBBlgTowF9X3KjgWmkoj9EIPLuzofjpPQEpU +wgbhAsO8beqbmmQCraIb1j4UOJdaCBN5gCpqLNkCgYEA0couSC4Fz2+BQCZ2W2xF +P/9ZutkvcRogNB7eyB9u6+ItEwAXREFNUX4s4R0gm11ZE2c+4No6BUp3oXHPH9Yf +Pwe+fYtpakfuRRDkMNBNKKDP1J9fLxAAEG2hjYSIdv4R6gmu5r2qHj3vTmKB0JBO +CTtXpfuGmXxx2xHs4yHvqdECgYAS8f4fCuXLwnTgN5dU9e9F4NS0rw2kN+qSPJWk +fGnj3jlD9nioaU+q/q0jYjAqHO6NKYjnsDwVsrvXUodfmjQOdV6Nsr5IPLhZ9M4F +y1FCaJC0OJijv9irrp+MWkM7xmYwMsDHfaz1fSHTgd0WBdDaNhEzaIiq4DdgGbF2 +7n8LwQKBgEvx0KL7fxljpu/UC7m21p7o6S2ZVNr8aTiaTqiNeYrfiCCt1sbYB/to +dHs1sgnUfRT7BfVpDgGTR0m/1IHp7jjvtQRkpCR/EyJxe8nYs/VERV4XhZb08tzo +3AlVnxWkYZ2WhzRSRbRXwuF+7xVSh/XDycXX5I48Xztz/8ZNq/W3 +-----END RSA PRIVATE KEY----- diff --git a/examples/customTls/self_signed_certificate_test.go b/examples/customTls/self_signed_certificate_test.go new file mode 100644 index 000000000..4f7177dcf --- /dev/null +++ b/examples/customTls/self_signed_certificate_test.go @@ -0,0 +1,86 @@ +package provider + +import ( + "fmt" + "os" + "github.com/pact-foundation/pact-go/dsl" + "github.com/pact-foundation/pact-go/utils" + "path/filepath" + "testing" + "crypto/tls" + "crypto/x509" + "github.com/pact-foundation/pact-go/types" + "io/ioutil" + "log" + "net/http" +) + +// An external HTTPS provider +func TestPact_SelfSignedTLSProvider(t *testing.T) { + go startServer() + + pact := createPact() + _, err := pact.VerifyProvider(t, types.VerifyRequest{ + ProviderBaseURL: fmt.Sprintf("https://localhost:%d", port), + PactURLs: []string{filepath.ToSlash(fmt.Sprintf("%s/consumer-selfsignedtls.json", pactDir))}, + CustomTLSConfig: &tls.Config{ + RootCAs: getCaCertPool(), + // InsecureSkipVerify: true, // Disable SSL verification altogether + }, + }) + + if err != nil { + t.Fatal(err) + } +} + +func HelloServer(w http.ResponseWriter, req *http.Request) { } + +func startServer() { + http.HandleFunc("/hello", HelloServer) + + // Setup HTTPS client + tlsConfig := &tls.Config{ + ClientCAs: getCaCertPool(), + ClientAuth: tls.NoClientCert, + } + tlsConfig.BuildNameToCertificate() + + server := &http.Server{ + Addr: fmt.Sprintf(":%d", port), + TLSConfig: tlsConfig, + } + + log.Fatalf("%v", server.ListenAndServeTLS("certs/server-cert.pem", "certs/server-key.pem")) +} + +// Configuration / Test Data +var dir, _ = os.Getwd() +var pactDir = fmt.Sprintf("%s/../pacts", dir) +var logDir = fmt.Sprintf("%s/log", dir) +var port, _ = utils.GetFreePort() + +// Setup the Pact client. +func createPact() dsl.Pact { + return dsl.Pact{ + Consumer: "consumer", + Provider: "selfsignedtls", + LogDir: logDir, + PactDir: pactDir, + DisableToolValidityCheck: true, + LogLevel: "DEBUG", + } +} + +// Custom certificate authority +func getCaCertPool() *x509.CertPool { + caCert, err := ioutil.ReadFile("certs/ca.pem") + if err != nil { + log.Fatal(err) + } + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + return caCertPool +} \ No newline at end of file diff --git a/examples/httpbin/httpbin_test.go b/examples/httpbin/httpbin_test.go index 6d1d46e83..d81b88787 100644 --- a/examples/httpbin/httpbin_test.go +++ b/examples/httpbin/httpbin_test.go @@ -2,21 +2,18 @@ package provider import ( "fmt" - "os" "path/filepath" "testing" - + "os" "github.com/pact-foundation/pact-go/dsl" - "github.com/pact-foundation/pact-go/types" "github.com/pact-foundation/pact-go/utils" + "github.com/pact-foundation/pact-go/types" ) // An external HTTPS provider -func TestPact_GinProvider(t *testing.T) { - +func TestPact_ExternalHttpsProvider(t *testing.T) { pact := createPact() - // Verify the Provider with local Pact Files _, err := pact.VerifyProvider(t, types.VerifyRequest{ ProviderBaseURL: "https://httpbin.org", PactURLs: []string{filepath.ToSlash(fmt.Sprintf("%s/consumer-httpbin.json", pactDir))}, @@ -37,11 +34,11 @@ var port, _ = utils.GetFreePort() // Setup the Pact client. func createPact() dsl.Pact { return dsl.Pact{ - Consumer: "jmarie", - Provider: "loginprovider", + Consumer: "consumer", + Provider: "httpbinprovider", LogDir: logDir, PactDir: pactDir, DisableToolValidityCheck: true, LogLevel: "DEBUG", } -} +} \ No newline at end of file diff --git a/examples/mux/provider/user_service_test.go b/examples/mux/provider/user_service_test.go index a759caeae..d262f2d77 100644 --- a/examples/mux/provider/user_service_test.go +++ b/examples/mux/provider/user_service_test.go @@ -19,7 +19,7 @@ import ( // The Provider verification func TestPact_MuxProvider(t *testing.T) { - go startInstrumentedProvider() + startProvider() pact := createPact() @@ -129,7 +129,7 @@ var stateHandlers = types.StateHandlers{ // Starts the provider API with hooks for provider states. // This essentially mirrors the main.go file, with extra routes added. -func startInstrumentedProvider() { +func startProvider() { mux := http.NewServeMux() mux.HandleFunc("/users/", IsAuthenticated(GetUser)) mux.HandleFunc("/login/", UserLogin) diff --git a/examples/pacts/consumer-selfsignedtls.json b/examples/pacts/consumer-selfsignedtls.json new file mode 100644 index 000000000..36cef42e4 --- /dev/null +++ b/examples/pacts/consumer-selfsignedtls.json @@ -0,0 +1,25 @@ +{ + "consumer": { + "name": "consumer" + }, + "provider": { + "name": "httpbin" + }, + "interactions": [ + { + "description": "A request to the hello self-signed API", + "request": { + "method": "GET", + "path": "/hello" + }, + "response": { + "status": 200 + } + } + ], + "metadata": { + "pactSpecification": { + "version": "2.0.0" + } + } +} diff --git a/proxy/http.go b/proxy/http.go index 84a1260d3..909c70a9a 100644 --- a/proxy/http.go +++ b/proxy/http.go @@ -41,6 +41,10 @@ type Options struct { // Internal request prefix for proxy to not rewrite InternalRequestPathPrefix string + + // Custom TLS Configuration for communicating with a Provider + // Useful when verifying self-signed services, MASSL etc. + CustomTLSConfig *tls.Config } // loggingMiddleware logs requests to the proxy @@ -78,8 +82,11 @@ func HTTPReverseProxy(options Options) (int, error) { Host: options.TargetAddress, Path: options.TargetPath, } + + // TODO: may be able to revert to the default single proxy + // and just override the transport! proxy := createProxy(url, options.InternalRequestPathPrefix) - proxy.Transport = debugTransport{} + proxy.Transport = customTransport{tlsConfig: options.CustomTLSConfig} if port == 0 { port, err = utils.GetFreePort() @@ -100,31 +107,36 @@ func HTTPReverseProxy(options Options) (int, error) { // https://stackoverflow.com/questions/52986853/how-to-debug-httputil-newsinglehostreverseproxy // Set the proxy.Transport field to an implementation that dumps the request before delegating to the default transport: -type debugTransport struct{} +type customTransport struct { + tlsConfig *tls.Config +} -func (debugTransport) RoundTrip(r *http.Request) (*http.Response, error) { +func (c customTransport) RoundTrip(r *http.Request) (*http.Response, error) { b, err := httputil.DumpRequestOut(r, false) if err != nil { return nil, err } log.Println("[TRACE] proxy outgoing request\n", string(b)) - var DefaultTransport http.RoundTripper = &http.Transport{ + transport := &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, DualStack: true, }).DialContext, - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - }, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, } + if c.tlsConfig != nil { + log.Println("[DEBUG] applying custom TLS config") + transport.TLSClientConfig = c.tlsConfig + } + var DefaultTransport http.RoundTripper = transport + res, err := DefaultTransport.RoundTrip(r) b, err = httputil.DumpResponse(res, false) log.Println("[TRACE] proxied server response\n", string(b)) diff --git a/scripts/pact.ps1 b/scripts/pact.ps1 index 62a16c72d..7b714da9d 100644 --- a/scripts/pact.ps1 +++ b/scripts/pact.ps1 @@ -70,7 +70,7 @@ foreach ($package in $packages) { Write-Host "--> Testing E2E examples" $env:PACT_INTEGRATED_TESTS=1 -$examples=@("github.com/pact-foundation/pact-go/examples/consumer/goconsumer", "github.com/pact-foundation/pact-go/examples/go-kit/provider", "github.com/pact-foundation/pact-go/examples/mux/provider", "github.com/pact-foundation/pact-go/examples/gin/provider") +$examples=@("github.com/pact-foundation/pact-go/examples/consumer/goconsumer", "github.com/pact-foundation/pact-go/examples/go-kit/provider", "github.com/pact-foundation/pact-go/examples/mux/provider", "github.com/pact-foundation/pact-go/examples/gin/provider", "github.com/pact-foundation/pact-go/examples/httpbin", "github.com/pact-foundation/pact-go/examples/customTls") foreach ($example in $examples) { Write-Host "Installing dependencies for example: $example" cd "$env:GOPATH\src\$example" diff --git a/scripts/pact.sh b/scripts/pact.sh index 0d955ef55..13d1fe46f 100755 --- a/scripts/pact.sh +++ b/scripts/pact.sh @@ -31,7 +31,7 @@ export PACT_BROKER_PASSWORD="O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1" export PATH="../build/pact/bin:${PATH}" step "Running E2E regression and example projects" -examples=("github.com/pact-foundation/pact-go/examples/consumer/goconsumer" "github.com/pact-foundation/pact-go/examples/go-kit/provider" "github.com/pact-foundation/pact-go/examples/mux/provider" "github.com/pact-foundation/pact-go/examples/gin/provider" "github.com/pact-foundation/pact-go/examples/messages/consumer" "github.com/pact-foundation/pact-go/examples/messages/provider" "github.com/pact-foundation/pact-go/examples/httpbin") +examples=("github.com/pact-foundation/pact-go/examples/consumer/goconsumer" "github.com/pact-foundation/pact-go/examples/go-kit/provider" "github.com/pact-foundation/pact-go/examples/mux/provider" "github.com/pact-foundation/pact-go/examples/gin/provider" "github.com/pact-foundation/pact-go/examples/messages/consumer" "github.com/pact-foundation/pact-go/examples/messages/provider" "github.com/pact-foundation/pact-go/examples/httpbin" "github.com/pact-foundation/pact-go/examples/customTls") for example in "${examples[@]}" do diff --git a/types/verify_request.go b/types/verify_request.go index 8a7b79956..d65c50401 100644 --- a/types/verify_request.go +++ b/types/verify_request.go @@ -1,6 +1,7 @@ package types import ( + "crypto/tls" "errors" "fmt" "log" @@ -84,6 +85,10 @@ type VerifyRequest struct { // runs the risk of changing the contract and breaking the real system. RequestFilter proxy.Middleware + // Custom TLS Configuration to use when making the requests to/from + // the Provider API. Useful for setting custom certificates, MASSL etc. + CustomTLSConfig *tls.Config + // Verbose increases verbosity of output // Deprecated Verbose bool diff --git a/vendor/github.com/go-kit/kit/LICENSE b/vendor/github.com/go-kit/kit/LICENSE deleted file mode 100644 index 9d83342ac..000000000 --- a/vendor/github.com/go-kit/kit/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Peter Bourgon - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/vendor/github.com/go-kit/kit/endpoint/doc.go b/vendor/github.com/go-kit/kit/endpoint/doc.go deleted file mode 100644 index 84e27b95d..000000000 --- a/vendor/github.com/go-kit/kit/endpoint/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Package endpoint defines an abstraction for RPCs. -// -// Endpoints are a fundamental building block for many Go kit components. -// Endpoints are implemented by servers, and called by clients. -package endpoint diff --git a/vendor/github.com/go-kit/kit/endpoint/endpoint.go b/vendor/github.com/go-kit/kit/endpoint/endpoint.go deleted file mode 100644 index 1b64f50ed..000000000 --- a/vendor/github.com/go-kit/kit/endpoint/endpoint.go +++ /dev/null @@ -1,28 +0,0 @@ -package endpoint - -import ( - "context" -) - -// Endpoint is the fundamental building block of servers and clients. -// It represents a single RPC method. -type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error) - -// Nop is an endpoint that does nothing and returns a nil error. -// Useful for tests. -func Nop(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil } - -// Middleware is a chainable behavior modifier for endpoints. -type Middleware func(Endpoint) Endpoint - -// Chain is a helper function for composing middlewares. Requests will -// traverse them in the order they're declared. That is, the first middleware -// is treated as the outermost middleware. -func Chain(outer Middleware, others ...Middleware) Middleware { - return func(next Endpoint) Endpoint { - for i := len(others) - 1; i >= 0; i-- { // reverse - next = others[i](next) - } - return outer(next) - } -} diff --git a/vendor/github.com/go-kit/kit/log/README.md b/vendor/github.com/go-kit/kit/log/README.md deleted file mode 100644 index 7222f8009..000000000 --- a/vendor/github.com/go-kit/kit/log/README.md +++ /dev/null @@ -1,147 +0,0 @@ -# package log - -`package log` provides a minimal interface for structured logging in services. -It may be wrapped to encode conventions, enforce type-safety, provide leveled -logging, and so on. It can be used for both typical application log events, -and log-structured data streams. - -## Structured logging - -Structured logging is, basically, conceding to the reality that logs are -_data_, and warrant some level of schematic rigor. Using a stricter, -key/value-oriented message format for our logs, containing contextual and -semantic information, makes it much easier to get insight into the -operational activity of the systems we build. Consequently, `package log` is -of the strong belief that "[the benefits of structured logging outweigh the -minimal effort involved](https://www.thoughtworks.com/radar/techniques/structured-logging)". - -Migrating from unstructured to structured logging is probably a lot easier -than you'd expect. - -```go -// Unstructured -log.Printf("HTTP server listening on %s", addr) - -// Structured -logger.Log("transport", "HTTP", "addr", addr, "msg", "listening") -``` - -## Usage - -### Typical application logging - -```go -w := log.NewSyncWriter(os.Stderr) -logger := log.NewLogfmtLogger(w) -logger.Log("question", "what is the meaning of life?", "answer", 42) - -// Output: -// question="what is the meaning of life?" answer=42 -``` - -### Contextual Loggers - -```go -func main() { - var logger log.Logger - logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr)) - logger = log.With(logger, "instance_id", 123) - - logger.Log("msg", "starting") - NewWorker(log.With(logger, "component", "worker")).Run() - NewSlacker(log.With(logger, "component", "slacker")).Run() -} - -// Output: -// instance_id=123 msg=starting -// instance_id=123 component=worker msg=running -// instance_id=123 component=slacker msg=running -``` - -### Interact with stdlib logger - -Redirect stdlib logger to Go kit logger. - -```go -import ( - "os" - stdlog "log" - kitlog "github.com/go-kit/kit/log" -) - -func main() { - logger := kitlog.NewJSONLogger(kitlog.NewSyncWriter(os.Stdout)) - stdlog.SetOutput(kitlog.NewStdlibAdapter(logger)) - stdlog.Print("I sure like pie") -} - -// Output: -// {"msg":"I sure like pie","ts":"2016/01/01 12:34:56"} -``` - -Or, if, for legacy reasons, you need to pipe all of your logging through the -stdlib log package, you can redirect Go kit logger to the stdlib logger. - -```go -logger := kitlog.NewLogfmtLogger(kitlog.StdlibWriter{}) -logger.Log("legacy", true, "msg", "at least it's something") - -// Output: -// 2016/01/01 12:34:56 legacy=true msg="at least it's something" -``` - -### Timestamps and callers - -```go -var logger log.Logger -logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr)) -logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller) - -logger.Log("msg", "hello") - -// Output: -// ts=2016-01-01T12:34:56Z caller=main.go:15 msg=hello -``` - -## Supported output formats - -- [Logfmt](https://brandur.org/logfmt) ([see also](https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write)) -- JSON - -## Enhancements - -`package log` is centered on the one-method Logger interface. - -```go -type Logger interface { - Log(keyvals ...interface{}) error -} -``` - -This interface, and its supporting code like is the product of much iteration -and evaluation. For more details on the evolution of the Logger interface, -see [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1), -a talk by [Chris Hines](https://github.com/ChrisHines). -Also, please see -[#63](https://github.com/go-kit/kit/issues/63), -[#76](https://github.com/go-kit/kit/pull/76), -[#131](https://github.com/go-kit/kit/issues/131), -[#157](https://github.com/go-kit/kit/pull/157), -[#164](https://github.com/go-kit/kit/issues/164), and -[#252](https://github.com/go-kit/kit/pull/252) -to review historical conversations about package log and the Logger interface. - -Value-add packages and suggestions, -like improvements to [the leveled logger](https://godoc.org/github.com/go-kit/kit/log/level), -are of course welcome. Good proposals should - -- Be composable with [contextual loggers](https://godoc.org/github.com/go-kit/kit/log#With), -- Not break the behavior of [log.Caller](https://godoc.org/github.com/go-kit/kit/log#Caller) in any wrapped contextual loggers, and -- Be friendly to packages that accept only an unadorned log.Logger. - -## Benchmarks & comparisons - -There are a few Go logging benchmarks and comparisons that include Go kit's package log. - -- [imkira/go-loggers-bench](https://github.com/imkira/go-loggers-bench) includes kit/log -- [uber-common/zap](https://github.com/uber-common/zap), a zero-alloc logging library, includes a comparison with kit/log diff --git a/vendor/github.com/go-kit/kit/log/doc.go b/vendor/github.com/go-kit/kit/log/doc.go deleted file mode 100644 index 918c0af46..000000000 --- a/vendor/github.com/go-kit/kit/log/doc.go +++ /dev/null @@ -1,116 +0,0 @@ -// Package log provides a structured logger. -// -// Structured logging produces logs easily consumed later by humans or -// machines. Humans might be interested in debugging errors, or tracing -// specific requests. Machines might be interested in counting interesting -// events, or aggregating information for off-line processing. In both cases, -// it is important that the log messages are structured and actionable. -// Package log is designed to encourage both of these best practices. -// -// Basic Usage -// -// The fundamental interface is Logger. Loggers create log events from -// key/value data. The Logger interface has a single method, Log, which -// accepts a sequence of alternating key/value pairs, which this package names -// keyvals. -// -// type Logger interface { -// Log(keyvals ...interface{}) error -// } -// -// Here is an example of a function using a Logger to create log events. -// -// func RunTask(task Task, logger log.Logger) string { -// logger.Log("taskID", task.ID, "event", "starting task") -// ... -// logger.Log("taskID", task.ID, "event", "task complete") -// } -// -// The keys in the above example are "taskID" and "event". The values are -// task.ID, "starting task", and "task complete". Every key is followed -// immediately by its value. -// -// Keys are usually plain strings. Values may be any type that has a sensible -// encoding in the chosen log format. With structured logging it is a good -// idea to log simple values without formatting them. This practice allows -// the chosen logger to encode values in the most appropriate way. -// -// Contextual Loggers -// -// A contextual logger stores keyvals that it includes in all log events. -// Building appropriate contextual loggers reduces repetition and aids -// consistency in the resulting log output. With and WithPrefix add context to -// a logger. We can use With to improve the RunTask example. -// -// func RunTask(task Task, logger log.Logger) string { -// logger = log.With(logger, "taskID", task.ID) -// logger.Log("event", "starting task") -// ... -// taskHelper(task.Cmd, logger) -// ... -// logger.Log("event", "task complete") -// } -// -// The improved version emits the same log events as the original for the -// first and last calls to Log. Passing the contextual logger to taskHelper -// enables each log event created by taskHelper to include the task.ID even -// though taskHelper does not have access to that value. Using contextual -// loggers this way simplifies producing log output that enables tracing the -// life cycle of individual tasks. (See the Contextual example for the full -// code of the above snippet.) -// -// Dynamic Contextual Values -// -// A Valuer function stored in a contextual logger generates a new value each -// time an event is logged. The Valuer example demonstrates how this feature -// works. -// -// Valuers provide the basis for consistently logging timestamps and source -// code location. The log package defines several valuers for that purpose. -// See Timestamp, DefaultTimestamp, DefaultTimestampUTC, Caller, and -// DefaultCaller. A common logger initialization sequence that ensures all log -// entries contain a timestamp and source location looks like this: -// -// logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout)) -// logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller) -// -// Concurrent Safety -// -// Applications with multiple goroutines want each log event written to the -// same logger to remain separate from other log events. Package log provides -// two simple solutions for concurrent safe logging. -// -// NewSyncWriter wraps an io.Writer and serializes each call to its Write -// method. Using a SyncWriter has the benefit that the smallest practical -// portion of the logging logic is performed within a mutex, but it requires -// the formatting Logger to make only one call to Write per log event. -// -// NewSyncLogger wraps any Logger and serializes each call to its Log method. -// Using a SyncLogger has the benefit that it guarantees each log event is -// handled atomically within the wrapped logger, but it typically serializes -// both the formatting and output logic. Use a SyncLogger if the formatting -// logger may perform multiple writes per log event. -// -// Error Handling -// -// This package relies on the practice of wrapping or decorating loggers with -// other loggers to provide composable pieces of functionality. It also means -// that Logger.Log must return an error because some -// implementations—especially those that output log data to an io.Writer—may -// encounter errors that cannot be handled locally. This in turn means that -// Loggers that wrap other loggers should return errors from the wrapped -// logger up the stack. -// -// Fortunately, the decorator pattern also provides a way to avoid the -// necessity to check for errors every time an application calls Logger.Log. -// An application required to panic whenever its Logger encounters -// an error could initialize its logger as follows. -// -// fmtlogger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout)) -// logger := log.LoggerFunc(func(keyvals ...interface{}) error { -// if err := fmtlogger.Log(keyvals...); err != nil { -// panic(err) -// } -// return nil -// }) -package log diff --git a/vendor/github.com/go-kit/kit/log/json_logger.go b/vendor/github.com/go-kit/kit/log/json_logger.go deleted file mode 100644 index 66094b4dd..000000000 --- a/vendor/github.com/go-kit/kit/log/json_logger.go +++ /dev/null @@ -1,89 +0,0 @@ -package log - -import ( - "encoding" - "encoding/json" - "fmt" - "io" - "reflect" -) - -type jsonLogger struct { - io.Writer -} - -// NewJSONLogger returns a Logger that encodes keyvals to the Writer as a -// single JSON object. Each log event produces no more than one call to -// w.Write. The passed Writer must be safe for concurrent use by multiple -// goroutines if the returned Logger will be used concurrently. -func NewJSONLogger(w io.Writer) Logger { - return &jsonLogger{w} -} - -func (l *jsonLogger) Log(keyvals ...interface{}) error { - n := (len(keyvals) + 1) / 2 // +1 to handle case when len is odd - m := make(map[string]interface{}, n) - for i := 0; i < len(keyvals); i += 2 { - k := keyvals[i] - var v interface{} = ErrMissingValue - if i+1 < len(keyvals) { - v = keyvals[i+1] - } - merge(m, k, v) - } - return json.NewEncoder(l.Writer).Encode(m) -} - -func merge(dst map[string]interface{}, k, v interface{}) { - var key string - switch x := k.(type) { - case string: - key = x - case fmt.Stringer: - key = safeString(x) - default: - key = fmt.Sprint(x) - } - - // We want json.Marshaler and encoding.TextMarshaller to take priority over - // err.Error() and v.String(). But json.Marshall (called later) does that by - // default so we force a no-op if it's one of those 2 case. - switch x := v.(type) { - case json.Marshaler: - case encoding.TextMarshaler: - case error: - v = safeError(x) - case fmt.Stringer: - v = safeString(x) - } - - dst[key] = v -} - -func safeString(str fmt.Stringer) (s string) { - defer func() { - if panicVal := recover(); panicVal != nil { - if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() { - s = "NULL" - } else { - panic(panicVal) - } - } - }() - s = str.String() - return -} - -func safeError(err error) (s interface{}) { - defer func() { - if panicVal := recover(); panicVal != nil { - if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() { - s = nil - } else { - panic(panicVal) - } - } - }() - s = err.Error() - return -} diff --git a/vendor/github.com/go-kit/kit/log/log.go b/vendor/github.com/go-kit/kit/log/log.go deleted file mode 100644 index 66a9e2fde..000000000 --- a/vendor/github.com/go-kit/kit/log/log.go +++ /dev/null @@ -1,135 +0,0 @@ -package log - -import "errors" - -// Logger is the fundamental interface for all log operations. Log creates a -// log event from keyvals, a variadic sequence of alternating keys and values. -// Implementations must be safe for concurrent use by multiple goroutines. In -// particular, any implementation of Logger that appends to keyvals or -// modifies or retains any of its elements must make a copy first. -type Logger interface { - Log(keyvals ...interface{}) error -} - -// ErrMissingValue is appended to keyvals slices with odd length to substitute -// the missing value. -var ErrMissingValue = errors.New("(MISSING)") - -// With returns a new contextual logger with keyvals prepended to those passed -// to calls to Log. If logger is also a contextual logger created by With or -// WithPrefix, keyvals is appended to the existing context. -// -// The returned Logger replaces all value elements (odd indexes) containing a -// Valuer with their generated value for each call to its Log method. -func With(logger Logger, keyvals ...interface{}) Logger { - if len(keyvals) == 0 { - return logger - } - l := newContext(logger) - kvs := append(l.keyvals, keyvals...) - if len(kvs)%2 != 0 { - kvs = append(kvs, ErrMissingValue) - } - return &context{ - logger: l.logger, - // Limiting the capacity of the stored keyvals ensures that a new - // backing array is created if the slice must grow in Log or With. - // Using the extra capacity without copying risks a data race that - // would violate the Logger interface contract. - keyvals: kvs[:len(kvs):len(kvs)], - hasValuer: l.hasValuer || containsValuer(keyvals), - } -} - -// WithPrefix returns a new contextual logger with keyvals prepended to those -// passed to calls to Log. If logger is also a contextual logger created by -// With or WithPrefix, keyvals is prepended to the existing context. -// -// The returned Logger replaces all value elements (odd indexes) containing a -// Valuer with their generated value for each call to its Log method. -func WithPrefix(logger Logger, keyvals ...interface{}) Logger { - if len(keyvals) == 0 { - return logger - } - l := newContext(logger) - // Limiting the capacity of the stored keyvals ensures that a new - // backing array is created if the slice must grow in Log or With. - // Using the extra capacity without copying risks a data race that - // would violate the Logger interface contract. - n := len(l.keyvals) + len(keyvals) - if len(keyvals)%2 != 0 { - n++ - } - kvs := make([]interface{}, 0, n) - kvs = append(kvs, keyvals...) - if len(kvs)%2 != 0 { - kvs = append(kvs, ErrMissingValue) - } - kvs = append(kvs, l.keyvals...) - return &context{ - logger: l.logger, - keyvals: kvs, - hasValuer: l.hasValuer || containsValuer(keyvals), - } -} - -// context is the Logger implementation returned by With and WithPrefix. It -// wraps a Logger and holds keyvals that it includes in all log events. Its -// Log method calls bindValues to generate values for each Valuer in the -// context keyvals. -// -// A context must always have the same number of stack frames between calls to -// its Log method and the eventual binding of Valuers to their value. This -// requirement comes from the functional requirement to allow a context to -// resolve application call site information for a Caller stored in the -// context. To do this we must be able to predict the number of logging -// functions on the stack when bindValues is called. -// -// Two implementation details provide the needed stack depth consistency. -// -// 1. newContext avoids introducing an additional layer when asked to -// wrap another context. -// 2. With and WithPrefix avoid introducing an additional layer by -// returning a newly constructed context with a merged keyvals rather -// than simply wrapping the existing context. -type context struct { - logger Logger - keyvals []interface{} - hasValuer bool -} - -func newContext(logger Logger) *context { - if c, ok := logger.(*context); ok { - return c - } - return &context{logger: logger} -} - -// Log replaces all value elements (odd indexes) containing a Valuer in the -// stored context with their generated value, appends keyvals, and passes the -// result to the wrapped Logger. -func (l *context) Log(keyvals ...interface{}) error { - kvs := append(l.keyvals, keyvals...) - if len(kvs)%2 != 0 { - kvs = append(kvs, ErrMissingValue) - } - if l.hasValuer { - // If no keyvals were appended above then we must copy l.keyvals so - // that future log events will reevaluate the stored Valuers. - if len(keyvals) == 0 { - kvs = append([]interface{}{}, l.keyvals...) - } - bindValues(kvs[:len(l.keyvals)]) - } - return l.logger.Log(kvs...) -} - -// LoggerFunc is an adapter to allow use of ordinary functions as Loggers. If -// f is a function with the appropriate signature, LoggerFunc(f) is a Logger -// object that calls f. -type LoggerFunc func(...interface{}) error - -// Log implements Logger by calling f(keyvals...). -func (f LoggerFunc) Log(keyvals ...interface{}) error { - return f(keyvals...) -} diff --git a/vendor/github.com/go-kit/kit/log/logfmt_logger.go b/vendor/github.com/go-kit/kit/log/logfmt_logger.go deleted file mode 100644 index a00305298..000000000 --- a/vendor/github.com/go-kit/kit/log/logfmt_logger.go +++ /dev/null @@ -1,62 +0,0 @@ -package log - -import ( - "bytes" - "io" - "sync" - - "github.com/go-logfmt/logfmt" -) - -type logfmtEncoder struct { - *logfmt.Encoder - buf bytes.Buffer -} - -func (l *logfmtEncoder) Reset() { - l.Encoder.Reset() - l.buf.Reset() -} - -var logfmtEncoderPool = sync.Pool{ - New: func() interface{} { - var enc logfmtEncoder - enc.Encoder = logfmt.NewEncoder(&enc.buf) - return &enc - }, -} - -type logfmtLogger struct { - w io.Writer -} - -// NewLogfmtLogger returns a logger that encodes keyvals to the Writer in -// logfmt format. Each log event produces no more than one call to w.Write. -// The passed Writer must be safe for concurrent use by multiple goroutines if -// the returned Logger will be used concurrently. -func NewLogfmtLogger(w io.Writer) Logger { - return &logfmtLogger{w} -} - -func (l logfmtLogger) Log(keyvals ...interface{}) error { - enc := logfmtEncoderPool.Get().(*logfmtEncoder) - enc.Reset() - defer logfmtEncoderPool.Put(enc) - - if err := enc.EncodeKeyvals(keyvals...); err != nil { - return err - } - - // Add newline to the end of the buffer - if err := enc.EndRecord(); err != nil { - return err - } - - // The Logger interface requires implementations to be safe for concurrent - // use by multiple goroutines. For this implementation that means making - // only one call to l.w.Write() for each call to Log. - if _, err := l.w.Write(enc.buf.Bytes()); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/go-kit/kit/log/nop_logger.go b/vendor/github.com/go-kit/kit/log/nop_logger.go deleted file mode 100644 index 1047d626c..000000000 --- a/vendor/github.com/go-kit/kit/log/nop_logger.go +++ /dev/null @@ -1,8 +0,0 @@ -package log - -type nopLogger struct{} - -// NewNopLogger returns a logger that doesn't do anything. -func NewNopLogger() Logger { return nopLogger{} } - -func (nopLogger) Log(...interface{}) error { return nil } diff --git a/vendor/github.com/go-kit/kit/log/stdlib.go b/vendor/github.com/go-kit/kit/log/stdlib.go deleted file mode 100644 index ff96b5dee..000000000 --- a/vendor/github.com/go-kit/kit/log/stdlib.go +++ /dev/null @@ -1,116 +0,0 @@ -package log - -import ( - "io" - "log" - "regexp" - "strings" -) - -// StdlibWriter implements io.Writer by invoking the stdlib log.Print. It's -// designed to be passed to a Go kit logger as the writer, for cases where -// it's necessary to redirect all Go kit log output to the stdlib logger. -// -// If you have any choice in the matter, you shouldn't use this. Prefer to -// redirect the stdlib log to the Go kit logger via NewStdlibAdapter. -type StdlibWriter struct{} - -// Write implements io.Writer. -func (w StdlibWriter) Write(p []byte) (int, error) { - log.Print(strings.TrimSpace(string(p))) - return len(p), nil -} - -// StdlibAdapter wraps a Logger and allows it to be passed to the stdlib -// logger's SetOutput. It will extract date/timestamps, filenames, and -// messages, and place them under relevant keys. -type StdlibAdapter struct { - Logger - timestampKey string - fileKey string - messageKey string -} - -// StdlibAdapterOption sets a parameter for the StdlibAdapter. -type StdlibAdapterOption func(*StdlibAdapter) - -// TimestampKey sets the key for the timestamp field. By default, it's "ts". -func TimestampKey(key string) StdlibAdapterOption { - return func(a *StdlibAdapter) { a.timestampKey = key } -} - -// FileKey sets the key for the file and line field. By default, it's "caller". -func FileKey(key string) StdlibAdapterOption { - return func(a *StdlibAdapter) { a.fileKey = key } -} - -// MessageKey sets the key for the actual log message. By default, it's "msg". -func MessageKey(key string) StdlibAdapterOption { - return func(a *StdlibAdapter) { a.messageKey = key } -} - -// NewStdlibAdapter returns a new StdlibAdapter wrapper around the passed -// logger. It's designed to be passed to log.SetOutput. -func NewStdlibAdapter(logger Logger, options ...StdlibAdapterOption) io.Writer { - a := StdlibAdapter{ - Logger: logger, - timestampKey: "ts", - fileKey: "caller", - messageKey: "msg", - } - for _, option := range options { - option(&a) - } - return a -} - -func (a StdlibAdapter) Write(p []byte) (int, error) { - result := subexps(p) - keyvals := []interface{}{} - var timestamp string - if date, ok := result["date"]; ok && date != "" { - timestamp = date - } - if time, ok := result["time"]; ok && time != "" { - if timestamp != "" { - timestamp += " " - } - timestamp += time - } - if timestamp != "" { - keyvals = append(keyvals, a.timestampKey, timestamp) - } - if file, ok := result["file"]; ok && file != "" { - keyvals = append(keyvals, a.fileKey, file) - } - if msg, ok := result["msg"]; ok { - keyvals = append(keyvals, a.messageKey, msg) - } - if err := a.Logger.Log(keyvals...); err != nil { - return 0, err - } - return len(p), nil -} - -const ( - logRegexpDate = `(?P[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?` - logRegexpTime = `(?P