Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions .github/workflows/go-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ jobs:
go-version: stable
check-latest: true
cache: true
cache-dependency-path: '**/go.sum'
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
version: latest
only-new-issues: true
skip-cache: true

test:
name: Unit tests
module-test:
name: Run unit tests on all modules in this repo
runs-on: ${{ matrix.os }}

strategy:
Expand All @@ -37,21 +38,48 @@ jobs:
go_version: ['oldstable', 'stable']

steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: '${{ matrix.go_version }}'
check-latest: true
cache: true

- uses: actions/checkout@v5
cache-dependency-path: '**/go.sum'
- name: Run unit tests
shell: bash
run: go test -v -race -coverprofile="coverage-${{ matrix.os }}.${{ matrix.go_version }}.out" -covermode=atomic -coverpkg=$(go list)/... ./...
env:
# *.coverage.* pattern is automatically detected by codecov
COVER_PROFILE: 'all_modules.coverage.${{ matrix.os }}.${{ matrix.go_version }}.out'
run: |
# when go1.25 becomes the oldstable, we may replace this bash with "go work test"
declare -a ALL_MODULES
BASH_MAJOR=$(echo $BASH_VERSION|cut -d'.' -f1)
if [[ "${BASH_MAJOR}" -ge 4 ]] ; then
mapfile ALL_MODULES < <(go list -f '{{.Dir}}/...' -m)
else
# for older bash versions, e.g. on macOS runner. This fallback will eventually disappear.
while read line ; do
ALL_MODULES+=("${line}")
done < <(go list -f '{{.Dir}}/...' -m)
fi
echo "::notice title=Modules found::${ALL_MODULES[@]}"

# with go.work file enabled, go test recognizes sub-modules and collects all packages to be covered
# without specifying -coverpkg.
go test -v -race -coverprofile="${COVER_PROFILE}" -covermode=atomic ${ALL_MODULES[@]}

- name: Upload coverage to codecov
uses: codecov/codecov-action@v5
with:
files: './coverage-${{ matrix.os }}.${{ matrix.go_version }}.out'
flags: '${{ matrix.go_version }}-${{ matrix.os }}'
fail_ci_if_error: false
verbose: true

test:
needs: [ module-test ]
name: Test
runs-on: ubuntu-latest
steps:
- name: Tests complete
run: |
echo "All tests completed"
3 changes: 2 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ linters:
- gocognit
- godot
- godox
- gomoddirectives # moved to mono-repo, multi-modules, so replace directives are needed
- gosmopolitan
- inamedparam
- intrange # disabled while < go1.22
#- intrange # disabled while < go1.22
- ireturn
- lll
- musttag
Expand Down
51 changes: 51 additions & 0 deletions client-middleware/opentracing/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module github.com/go-openapi/runtime/client-middleware/opentracing

require (
github.com/go-openapi/runtime v0.28.0
github.com/go-openapi/strfmt v0.23.0
github.com/opentracing/opentracing-go v1.2.0
github.com/stretchr/testify v1.11.1
)

require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.2 // indirect
github.com/go-openapi/jsonpointer v0.22.0 // indirect
github.com/go-openapi/jsonreference v0.21.1 // indirect
github.com/go-openapi/loads v0.22.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/swag v0.24.1 // indirect
github.com/go-openapi/swag/cmdutils v0.24.0 // indirect
github.com/go-openapi/swag/conv v0.24.0 // indirect
github.com/go-openapi/swag/fileutils v0.24.0 // indirect
github.com/go-openapi/swag/jsonname v0.24.0 // indirect
github.com/go-openapi/swag/jsonutils v0.24.0 // indirect
github.com/go-openapi/swag/loading v0.24.0 // indirect
github.com/go-openapi/swag/mangling v0.24.0 // indirect
github.com/go-openapi/swag/netutils v0.24.0 // indirect
github.com/go-openapi/swag/stringutils v0.24.0 // indirect
github.com/go-openapi/swag/typeutils v0.24.0 // indirect
github.com/go-openapi/swag/yamlutils v0.24.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.mongodb.org/mongo-driver v1.17.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
golang.org/x/sync v0.17.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace github.com/go-openapi/runtime => ../..

go 1.24.0
70 changes: 70 additions & 0 deletions client-middleware/opentracing/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.2 h1:rdxhzcBUazEcGccKqbY1Y7NS8FDcMyIRr0934jrYnZg=
github.com/go-openapi/jsonpointer v0.22.0 h1:TmMhghgNef9YXxTu1tOopo+0BGEytxA+okbry0HjZsM=
github.com/go-openapi/jsonreference v0.21.1 h1:bSKrcl8819zKiOgxkbVNRUBIr6Wwj9KYrDbMjRs0cDA=
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.24.1 h1:DPdYTZKo6AQCRqzwr/kGkxJzHhpKxZ9i/oX0zag+MF8=
github.com/go-openapi/swag/cmdutils v0.24.0 h1:KlRCffHwXFI6E5MV9n8o8zBRElpY4uK4yWyAMWETo9I=
github.com/go-openapi/swag/conv v0.24.0 h1:ejB9+7yogkWly6pnruRX45D1/6J+ZxRu92YFivx54ik=
github.com/go-openapi/swag/fileutils v0.24.0 h1:U9pCpqp4RUytnD689Ek/N1d2N/a//XCeqoH508H5oak=
github.com/go-openapi/swag/jsonname v0.24.0 h1:2wKS9bgRV/xB8c62Qg16w4AUiIrqqiniJFtZGi3dg5k=
github.com/go-openapi/swag/jsonutils v0.24.0 h1:F1vE1q4pg1xtO3HTyJYRmEuJ4jmIp2iZ30bzW5XgZts=
github.com/go-openapi/swag/loading v0.24.0 h1:ln/fWTwJp2Zkj5DdaX4JPiddFC5CHQpvaBKycOlceYc=
github.com/go-openapi/swag/mangling v0.24.0 h1:PGOQpViCOUroIeak/Uj/sjGAq9LADS3mOyjznmHy2pk=
github.com/go-openapi/swag/netutils v0.24.0 h1:Bz02HRjYv8046Ycg/w80q3g9QCWeIqTvlyOjQPDjD8w=
github.com/go-openapi/swag/stringutils v0.24.0 h1:i4Z/Jawf9EvXOLUbT97O0HbPUja18VdBxeadyAqS1FM=
github.com/go-openapi/swag/typeutils v0.24.0 h1:d3szEGzGDf4L2y1gYOSSLeK6h46F+zibnEas2Jm/wIw=
github.com/go-openapi/swag/yamlutils v0.24.0 h1:bhw4894A7Iw6ne+639hsBNRHg9iZg/ISrOVr+sJGp4c=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package client
package opentracing

import (
"fmt"
Expand Down Expand Up @@ -27,7 +27,7 @@ func newOpenTracingTransport(transport runtime.ClientTransport, host string, opt
}
}

func (t *tracingTransport) Submit(op *runtime.ClientOperation) (interface{}, error) {
func (t *tracingTransport) Submit(op *runtime.ClientOperation) (any, error) {
if op.Context == nil {
return t.transport.Submit(op)
}
Expand All @@ -47,7 +47,7 @@ func (t *tracingTransport) Submit(op *runtime.ClientOperation) (interface{}, err
return params.WriteToRequest(req, reg)
})

op.Reader = runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
op.Reader = runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (any, error) {
if span != nil {
code := response.Code()
ext.HTTPStatusCode.Set(span, uint16(code)) //nolint:gosec // safe to convert regular HTTP codes, no adverse impact other than a garbled trace when converting a code larger than 65535
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package client
package opentracing

import (
"bytes"
"context"
"io"
"testing"

"github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
Expand Down Expand Up @@ -39,10 +40,10 @@ type mockRuntime struct {
req runtime.TestClientRequest
}

func (m *mockRuntime) Submit(operation *runtime.ClientOperation) (interface{}, error) {
func (m *mockRuntime) Submit(operation *runtime.ClientOperation) (any, error) {
_ = operation.Params.WriteToRequest(&m.req, nil)
_, _ = operation.Reader.ReadResponse(&tres{}, nil)
return map[string]interface{}{}, nil
return map[string]any{}, nil
}

func testOperation(ctx context.Context) *runtime.ClientOperation {
Expand All @@ -52,14 +53,14 @@ func testOperation(ctx context.Context) *runtime.ClientOperation {
PathPattern: "/kubernetes-clusters/{cluster_id}",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{schemeHTTPS},
Reader: runtime.ClientResponseReaderFunc(func(runtime.ClientResponse, runtime.Consumer) (interface{}, error) {
Schemes: []string{"https"},
Reader: runtime.ClientResponseReaderFunc(func(runtime.ClientResponse, runtime.Consumer) (any, error) {
return nil, nil
}),
Params: runtime.ClientRequestWriterFunc(func(_ runtime.ClientRequest, _ strfmt.Registry) error {
return nil
}),
AuthInfo: PassThroughAuth,
AuthInfo: client.PassThroughAuth,
Context: ctx,
}
}
Expand Down Expand Up @@ -107,7 +108,7 @@ func testSubmit(t *testing.T, operation *runtime.ClientOperation, tracer *mocktr
if expectedSpans == 1 {
span := tracer.FinishedSpans()[0]
assert.Equal(t, "getCluster", span.OperationName)
assert.Equal(t, map[string]interface{}{
assert.Equal(t, map[string]any{
"component": "go-openapi",
"http.method": "GET",
"http.path": "/kubernetes-clusters/{cluster_id}",
Expand Down
19 changes: 19 additions & 0 deletions client-middleware/opentracing/runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package opentracing

import (
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/client"
opentracing "github.com/opentracing/opentracing-go"
)

// WithOpenTracing adds opentracing support to the provided runtime.
// A new client span is created for each request.
//
// If the context of the client operation does not contain an active span, no span is created.
// The provided opts are applied to each spans - for example to add global tags.
//
// This method is provided to continue supporting users of [github.com/go-openapi/runtime] who
// still rely on opentracing and have not been able to transition to opentelemetry yet.
func WithOpenTracing(r *client.Runtime, opts ...opentracing.StartSpanOption) runtime.ClientTransport {
return newOpenTracingTransport(r, r.Host, opts)
}
58 changes: 58 additions & 0 deletions client/mock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package client

import (
"bytes"
"context"
"io"

"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
)

type mockRuntime struct {
req runtime.TestClientRequest
}

func (m *mockRuntime) Submit(operation *runtime.ClientOperation) (any, error) {
_ = operation.Params.WriteToRequest(&m.req, nil)
_, _ = operation.Reader.ReadResponse(&tres{}, nil)
return map[string]any{}, nil
}

type tres struct {
}

func (r tres) Code() int {
return 490
}
func (r tres) Message() string {
return "the message"
}
func (r tres) GetHeader(_ string) string {
return "the header"
}
func (r tres) GetHeaders(_ string) []string {
return []string{"the headers", "the headers2"}
}
func (r tres) Body() io.ReadCloser {
return io.NopCloser(bytes.NewBufferString("the content"))
}

func testOperation(ctx context.Context) *runtime.ClientOperation {
return &runtime.ClientOperation{
ID: "getCluster",
Method: "GET",
PathPattern: "/kubernetes-clusters/{cluster_id}",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"https"},
Reader: runtime.ClientResponseReaderFunc(func(runtime.ClientResponse, runtime.Consumer) (any, error) {
return nil, nil
}),
Params: runtime.ClientRequestWriterFunc(func(_ runtime.ClientRequest, _ strfmt.Registry) error {
return nil
}),
AuthInfo: PassThroughAuth,
Context: ctx,
}
}
2 changes: 1 addition & 1 deletion client/opentelemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func assertOpenTelemetrySubmit(t *testing.T, operation *runtime.ClientOperation,

span := spans[0]
assert.Equal(t, "getCluster", span.Name)
assert.Equal(t, "go-openapi", span.InstrumentationLibrary.Name)
assert.Equal(t, "go-openapi", span.InstrumentationScope.Name)
assert.Equal(t, codes.Error, span.Status.Code)
assert.Equal(t, []attribute.KeyValue{
attribute.String("net.peer.name", "remote_host"),
Expand Down
Loading
Loading