From 2a4dd70bce663097ab98c2e1430131b195da312a Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Tue, 26 Mar 2024 17:12:15 +0100 Subject: [PATCH] feat: allow configuration of User-Agent for client --- .github/workflows/golangci-lint.yml | 2 +- .../integration-test-enterprise-nightly.yaml | 2 +- .../workflows/integration-test-nightly.yaml | 2 +- CHANGELOG.md | 8 +++++ go.mod | 4 ++- go.sum | 9 +++++ kong/client.go | 5 +++ kong/custom/entity_crud_test.go | 4 +-- kong/route_service_test.go | 4 +-- kong/user_agent_test.go | 34 +++++++++++++++++++ kong/utils.go | 4 +-- kong/utils_test.go | 2 +- kong/workspace_service.go | 16 ++++----- 13 files changed, 77 insertions(+), 19 deletions(-) create mode 100644 kong/user_agent_test.go diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 6fa9b2fbc..b3058f39b 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -27,7 +27,7 @@ jobs: with: go-version-file: go.mod - name: Setup golangci-lint - uses: golangci/golangci-lint-action@v3.7.0 + uses: golangci/golangci-lint-action@v4 with: # actions/setup-go@v5 introduced automatic cache handling so skip cache here skip-cache: true diff --git a/.github/workflows/integration-test-enterprise-nightly.yaml b/.github/workflows/integration-test-enterprise-nightly.yaml index bc776d837..fa7079240 100644 --- a/.github/workflows/integration-test-enterprise-nightly.yaml +++ b/.github/workflows/integration-test-enterprise-nightly.yaml @@ -61,7 +61,7 @@ jobs: - name: Setup go uses: actions/setup-go@v5 with: - go-version: '^1.19' + go-version-file: go.mod - name: Setup Kong run: make setup-kong-ee - name: Run tests diff --git a/.github/workflows/integration-test-nightly.yaml b/.github/workflows/integration-test-nightly.yaml index 333fe148a..927bb0a49 100644 --- a/.github/workflows/integration-test-nightly.yaml +++ b/.github/workflows/integration-test-nightly.yaml @@ -37,7 +37,7 @@ jobs: - name: Setup go uses: actions/setup-go@v5 with: - go-version: '^1.19' + go-version-file: go.mod - name: Setup Kong run: make setup-kong-${{ matrix.dbmode }} - name: Run tests diff --git a/CHANGELOG.md b/CHANGELOG.md index 3136b9801..8e4544cc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Table of Contents +- [v0.52.0](#v0520) - [v0.51.0](#v0510) - [v0.50.0](#v0500) - [v0.49.0](#v0490) @@ -63,6 +64,13 @@ - [0.2.0](#020) - [0.1.0](#010) +## [v0.52.0] + +> Release date: 2024/03/26 + +- Allow configuration of `User-Agent` for the client. + [#427](https://github.com/Kong/go-kong/pull/427) + ## [v0.51.0] > Release date: 2024/01/23 diff --git a/go.mod b/go.mod index 8ad998e1f..7115680d0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/kong/go-kong -go 1.19 +go 1.21 + +toolchain go1.22.1 replace github.com/imdario/mergo v0.3.12 => github.com/Kong/mergo v0.3.13 diff --git a/go.sum b/go.sum index ad6e70985..c873403f4 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,7 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 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/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= @@ -52,6 +53,7 @@ github.com/kong/semver/v4 v4.0.1/go.mod h1:LImQ0oT15pJvSns/hs2laLca2zcYoHu5EsSNY github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -66,10 +68,13 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= 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.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -98,13 +103,16 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= @@ -137,6 +145,7 @@ k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/kong/client.go b/kong/client.go index 2fc6570b4..98abedb80 100644 --- a/kong/client.go +++ b/kong/client.go @@ -38,6 +38,7 @@ type Client struct { client *http.Client baseRootURL string workspace string // Do not access directly. Use Workspace()/SetWorkspace(). + UserAgent string // User-Agent for the client. workspaceLock sync.RWMutex // Synchronizes access to workspace. common service ConsumerGroupConsumers AbstractConsumerGroupConsumerService @@ -252,6 +253,10 @@ func (c *Client) Do( req *http.Request, v interface{}, ) (*Response, error) { + if c.UserAgent != "" && req != nil { + req.Header.Add("User-Agent", c.UserAgent) + } + resp, err := c.DoRAW(ctx, req) if err != nil { return nil, err diff --git a/kong/custom/entity_crud_test.go b/kong/custom/entity_crud_test.go index b0313d5a3..ad9ff8e27 100644 --- a/kong/custom/entity_crud_test.go +++ b/kong/custom/entity_crud_test.go @@ -95,7 +95,7 @@ func TestEntityCRUDDefinition(t *testing.T) { func TestEntityCRUDUnmarshal(t *testing.T) { assert := assert.New(t) - t.Run("unmarshal JSON into EntityCRUDDefinition", func(t *testing.T) { + t.Run("unmarshal JSON into EntityCRUDDefinition", func(_ *testing.T) { bytes := []byte(`{ "name": "name", "crud": "crud-path", @@ -109,7 +109,7 @@ func TestEntityCRUDUnmarshal(t *testing.T) { assert.Equal("primary-key", def.PrimaryKey) }) - t.Run("unmarshal YAML into EntityCRUDDefinition", func(t *testing.T) { + t.Run("unmarshal YAML into EntityCRUDDefinition", func(_ *testing.T) { var def EntityCRUDDefinition bytes := []byte(` name: "name" diff --git a/kong/route_service_test.go b/kong/route_service_test.go index c42f45cc5..6e38e265b 100644 --- a/kong/route_service_test.go +++ b/kong/route_service_test.go @@ -423,7 +423,7 @@ func TestRoutesValidationExpressions(T *testing.T) { valid: true, }, } { - T.Run(tC.name, func(t *testing.T) { + T.Run(tC.name, func(_ *testing.T) { ok, msg, err := client.Routes.Validate(defaultCtx, tC.route) require.NoError(err) require.Equal(tC.valid, ok) @@ -492,7 +492,7 @@ func TestRoutesValidationTraditionalCompatible(T *testing.T) { msgStartWith: "schema violation (paths.2: invalid regex:", }, } { - T.Run(tC.name, func(t *testing.T) { + T.Run(tC.name, func(_ *testing.T) { ok, msg, err := client.Routes.Validate(defaultCtx, tC.route) require.NoError(err) require.Equal(tC.valid, ok) diff --git a/kong/user_agent_test.go b/kong/user_agent_test.go new file mode 100644 index 000000000..434031dae --- /dev/null +++ b/kong/user_agent_test.go @@ -0,0 +1,34 @@ +package kong + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestUserAgentHeader(t *testing.T) { + collectedUserAgents := make([]string, 0, 3) + server := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { + collectedUserAgents = append(collectedUserAgents, req.Header.Get("User-Agent")) + })) + t.Cleanup(server.Close) + + const userAgent = "go-kong/v1.2.3" + + client, err := NewClient(&server.URL, nil) + require.NoError(t, err) + client.UserAgent = userAgent + + testingID := "test-id" + _, _ = client.Licenses.Get(context.Background(), &testingID) + require.Equal(t, collectedUserAgents[0], userAgent) + + _, _, _ = client.Plugins.List(context.Background(), nil) //nolint:dogsled + require.Equal(t, collectedUserAgents[1], userAgent) + + _, _ = client.Vaults.Create(context.Background(), &Vault{}) + require.Equal(t, collectedUserAgents[2], userAgent) +} diff --git a/kong/utils.go b/kong/utils.go index 0b3479682..c6902f20f 100644 --- a/kong/utils.go +++ b/kong/utils.go @@ -206,7 +206,7 @@ func fillConfigRecord(schema gjson.Result, config Configuration) Configuration { res := config.DeepCopy() value := schema.Get("fields") - value.ForEach(func(key, value gjson.Result) bool { + value.ForEach(func(_, value gjson.Result) bool { // get the key name ms := value.Map() fname := "" @@ -427,7 +427,7 @@ func flattenJSONSchema(value gjson.Result) Schema { func flattenLuaSchema(value gjson.Result) Schema { results := Schema{} - value.ForEach(func(key, value gjson.Result) bool { + value.ForEach(func(_, value gjson.Result) bool { // get the key name ms := value.Map() fname := "" diff --git a/kong/utils_test.go b/kong/utils_test.go index 4546d58a2..ed323a6ae 100644 --- a/kong/utils_test.go +++ b/kong/utils_test.go @@ -1566,7 +1566,7 @@ func TestFillTargetDefaultsFromJSONSchema(t *testing.T) { } func TestHTTPClientWithHeaders(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(200) })) defer srv.Close() diff --git a/kong/workspace_service.go b/kong/workspace_service.go index 9b785658b..0ffd3a61d 100644 --- a/kong/workspace_service.go +++ b/kong/workspace_service.go @@ -29,12 +29,12 @@ type AbstractWorkspaceService interface { // of the entity that was added to the workspace. // // Deprecated: Kong 2.x removed this endpoint. - AddEntities(ctx context.Context, workspaceNameOrID *string, entityIds *string) (*[]map[string]interface{}, error) + AddEntities(ctx context.Context, workspaceNameOrID *string, entityIDs *string) (*[]map[string]interface{}, error) // DeleteEntities deletes entity ids given as a a comma delimited string // to a given workspace in Kong. // // Deprecated: Kong 2.x removed this endpoint. - DeleteEntities(ctx context.Context, workspaceNameOrID *string, entityIds *string) error + DeleteEntities(ctx context.Context, workspaceNameOrID *string, entityIDs *string) error // ListEntities fetches a list of all workspace entities in Kong. // // Deprecated: Kong 2.x removed this endpoint. @@ -210,9 +210,9 @@ func (s *WorkspaceService) ListAll(ctx context.Context) ([]*Workspace, error) { // // Deprecated: Kong 2.x removed this endpoint. func (s *WorkspaceService) AddEntities(ctx context.Context, - workspaceNameOrID *string, entityIds *string, + workspaceNameOrID *string, entityIDs *string, ) (*[]map[string]interface{}, error) { - if entityIds == nil { + if entityIDs == nil { return nil, fmt.Errorf("entityIds cannot be nil") } @@ -220,7 +220,7 @@ func (s *WorkspaceService) AddEntities(ctx context.Context, var entities struct { Entities *string `json:"entities,omitempty"` } - entities.Entities = entityIds + entities.Entities = entityIDs req, err := s.client.NewRequest("POST", endpoint, nil, entities) if err != nil { @@ -241,9 +241,9 @@ func (s *WorkspaceService) AddEntities(ctx context.Context, // // Deprecated: Kong 2.x removed this endpoint. func (s *WorkspaceService) DeleteEntities(ctx context.Context, - workspaceNameOrID *string, entityIds *string, + workspaceNameOrID *string, entityIDs *string, ) error { - if entityIds == nil { + if entityIDs == nil { return fmt.Errorf("entityIds cannot be nil") } @@ -251,7 +251,7 @@ func (s *WorkspaceService) DeleteEntities(ctx context.Context, var entities struct { Entities *string `json:"entities,omitempty"` } - entities.Entities = entityIds + entities.Entities = entityIDs req, err := s.client.NewRequest("DELETE", endpoint, nil, entities) if err != nil {