diff --git a/.mockery.yml b/.mockery.yml index 2d14758f..b0261908 100644 --- a/.mockery.yml +++ b/.mockery.yml @@ -12,7 +12,7 @@ packages: queryorchestration/internal/server/runner: interfaces: Controller: - queryorchestration/pkg/queryService: + queryorchestration/pkg/queryAPI: interfaces: ClientWithResponsesInterface: ClientInterface: diff --git a/README.md b/README.md index 7815b9ea..d7d74fc0 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,21 @@ This repository contains the DoczyAI code. -Using the following project as a baseline: https://github.com/golang-standards/project-layout. +Using the following project as a baseline: `https://github.com/golang-standards/project-layout`. ## Installation and Usage - Install devbox: `https://www.jetify.com/docs/devbox/installing_devbox` - Ubuntu/MacOS: `curl -fsSL https://get.jetify.com/devbox | bash` + - NixOS: `devbox` - Install docker: `https://docs.docker.com/engine/install/` - (IF NECESSARY) Ensure user in docker group and docker group is in sudo group - ``` + + ```sh sudo groupadd docker sudo usermod -aG docker $USER ``` + - Run `touch .env` to create `.env` file for custom environment variables - Run `devbox shell` to enter the environment - Run `task fullsuite` to run all tests that ensure the current state @@ -54,14 +57,14 @@ This will: **Service** - This term is used internally in order to refer to commands that get deployed as APIs. **Runner** - This term is used internally in order to refer to commands that get deployed as consumers of a queue. -### Creating a new Service +### Creating a new API -1. Add a file named `.yml`. The service name is important, as it will be used as a reference throughout the codebase. The service name must be in the format `Service`. E.g. queryService, ClientService +1. Add a file named `.yml`. The api name is important, as it will be used as a reference throughout the codebase. The api name must be in the format `API`. E.g. queryAPI, ClientAPI 2. Run `task openapi:generate`. This will generate the following: - - A location to implement the server-side functions in `./api//`, as well as generated functions, models and swagger docs. - - A location with the client-side code in `./pkg//` -3. Implement the controllers in `./api//` -4. Create a command in `./cmd//main.go` which creates a new instance from `./internal/api` + a. A location to implement the server-side functions in `./api//`, as well as generated functions, models and swagger docs. + b. A location with the client-side code in `./pkg//` +3. Implement the controllers in `./api//` +4. Create a command in `./cmd//main.go` which creates a new instance from `./internal/api` ### Creating a new Runner diff --git a/api/clientSyncRunner/runner_test.go b/api/clientSyncRunner/runner_test.go index d69ff6c3..17596bb5 100644 --- a/api/clientSyncRunner/runner_test.go +++ b/api/clientSyncRunner/runner_test.go @@ -54,7 +54,7 @@ func TestQueryRunner(t *testing.T) { ID: uuid.New(), } bodyBytes, err := json.Marshal(bod) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, diff --git a/api/docCleanRunner/runner_test.go b/api/docCleanRunner/runner_test.go index eef10d3b..eebfa82a 100644 --- a/api/docCleanRunner/runner_test.go +++ b/api/docCleanRunner/runner_test.go @@ -61,13 +61,13 @@ func TestDocCleanRunner(t *testing.T) { ID: uuid.New(), } bodyBytes, err := json.Marshal(bod) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, } - doc := document.Document{ + doc := document.DocumentSummary{ ID: bod.ID, ClientID: uuid.New(), Hash: "example_hash", @@ -82,7 +82,7 @@ func TestDocCleanRunner(t *testing.T) { pgxmock.NewRows([]string{"isclean"}). AddRow(false), ) - pool.ExpectQuery("name: GetDocument :one").WithArgs(dbid). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(dbid). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(dbid, database.MustToDBUUID(doc.ClientID), doc.Hash), diff --git a/api/docInitRunner/runner.go b/api/docInitRunner/runner.go index a4593727..d77227d9 100644 --- a/api/docInitRunner/runner.go +++ b/api/docInitRunner/runner.go @@ -53,17 +53,17 @@ type S3EventRecord struct { EventSource string `json:"eventSource"` AwsRegion string `json:"awsRegion"` EventTime string `json:"eventTime"` - EventName string `json:"eventName"` + EventName EventS3 `json:"eventName"` S3 S3EventRecordDetails `json:"s3"` } type S3EventNotification struct { Records []S3EventRecord `json:"Records"` } -type S3Events string +type EventS3 string const ( - S3EventObjectCreatedPut = "ObjectCreated:Put" + EventS3ObjectCreatedPut = "ObjectCreated:Put" ) func (s Runner) Process(ctx context.Context, req *types.Message) bool { @@ -118,6 +118,6 @@ func (s Runner) processRecord(ctx context.Context, record S3EventRecord) error { return nil } -func (s Runner) isSupportedEvent(name string) bool { - return name == S3EventObjectCreatedPut +func (s Runner) isSupportedEvent(name EventS3) bool { + return name == EventS3ObjectCreatedPut } diff --git a/api/docInitRunner/runner_test.go b/api/docInitRunner/runner_test.go index 5fa7c0a0..e1dce040 100644 --- a/api/docInitRunner/runner_test.go +++ b/api/docInitRunner/runner_test.go @@ -51,7 +51,7 @@ func TestDocInitRunner(t *testing.T) { clientId := uuid.New() bucketName := "bucketName" location := fmt.Sprintf("%s/aaa", clientId) - docinfo := document.Document{ + docinfo := document.DocumentSummary{ ID: uuid.New(), ClientID: clientId, Hash: "example_hash", @@ -59,7 +59,7 @@ func TestDocInitRunner(t *testing.T) { doc := S3EventNotification{ Records: []S3EventRecord{ { - EventName: "ObjectCreated:Put", + EventName: EventS3ObjectCreatedPut, S3: S3EventRecordDetails{ Bucket: S3Bucket{ Name: bucketName, @@ -73,7 +73,7 @@ func TestDocInitRunner(t *testing.T) { }, } bodyBytes, err := json.Marshal(doc) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, @@ -91,7 +91,7 @@ func TestDocInitRunner(t *testing.T) { pool.ExpectExec("name: AddDocumentEntry :exec").WithArgs(database.MustToDBUUID(docinfo.ID), bucketName, location). WillReturnResult(pgxmock.NewResult("", 1)) pool.ExpectCommit() - pool.ExpectQuery("name: GetDocument :one").WithArgs(database.MustToDBUUID(docinfo.ID)). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(database.MustToDBUUID(docinfo.ID)). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(database.MustToDBUUID(docinfo.ID), database.MustToDBUUID(docinfo.ClientID), "example"), @@ -144,13 +144,13 @@ func TestProcessRecord(t *testing.T) { } bucketName := "bucketName" location := fmt.Sprintf("%s/aaa", j.ID.String()) - docinfo := document.Document{ + docinfo := document.DocumentSummary{ ID: uuid.New(), ClientID: j.ID, Hash: "example_hash", } record := S3EventRecord{ - EventName: S3EventObjectCreatedPut, + EventName: EventS3ObjectCreatedPut, S3: S3EventRecordDetails{ Bucket: S3Bucket{ Name: bucketName, @@ -174,7 +174,7 @@ func TestProcessRecord(t *testing.T) { pool.ExpectExec("name: AddDocumentEntry :exec").WithArgs(database.MustToDBUUID(docinfo.ID), bucketName, location). WillReturnResult(pgxmock.NewResult("", 1)) pool.ExpectCommit() - pool.ExpectQuery("name: GetDocument :one").WithArgs(database.MustToDBUUID(docinfo.ID)). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(database.MustToDBUUID(docinfo.ID)). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(database.MustToDBUUID(docinfo.ID), database.MustToDBUUID(docinfo.ClientID), "example"), @@ -191,7 +191,7 @@ func TestProcessRecord(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = runner.processRecord(ctx, record) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("invalid_event", func(t *testing.T) { record := S3EventRecord{ @@ -199,12 +199,12 @@ func TestProcessRecord(t *testing.T) { } err = runner.processRecord(ctx, record) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("invalid id", func(t *testing.T) { location := "cc/aaa" record := S3EventRecord{ - EventName: S3EventObjectCreatedPut, + EventName: EventS3ObjectCreatedPut, S3: S3EventRecordDetails{ Object: S3Object{ Key: location, @@ -213,7 +213,7 @@ func TestProcessRecord(t *testing.T) { } err = runner.processRecord(ctx, record) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -221,7 +221,7 @@ func TestIsSupportedEvent(t *testing.T) { runner := Runner{} t.Run("put", func(t *testing.T) { - assert.True(t, runner.isSupportedEvent(S3EventObjectCreatedPut)) + assert.True(t, runner.isSupportedEvent(EventS3ObjectCreatedPut)) }) t.Run("invalid", func(t *testing.T) { assert.False(t, runner.isSupportedEvent("invalid")) diff --git a/api/docSyncRunner/runner_test.go b/api/docSyncRunner/runner_test.go index 1f28d3c5..b8e30bfa 100644 --- a/api/docSyncRunner/runner_test.go +++ b/api/docSyncRunner/runner_test.go @@ -55,7 +55,7 @@ func TestDocInitRunner(t *testing.T) { j := client.Client{ ID: uuid.New(), } - docinfo := document.Document{ + docinfo := document.DocumentSummary{ ID: uuid.New(), ClientID: j.ID, } @@ -63,13 +63,13 @@ func TestDocInitRunner(t *testing.T) { ID: docinfo.ID, } bodyBytes, err := json.Marshal(doc) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, } - pool.ExpectQuery("name: GetDocument :one").WithArgs(database.MustToDBUUID(docinfo.ID)). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(database.MustToDBUUID(docinfo.ID)). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(database.MustToDBUUID(docinfo.ID), database.MustToDBUUID(docinfo.ClientID), "example"), diff --git a/api/docTextRunner/runner_test.go b/api/docTextRunner/runner_test.go index 2a0943df..25438ca1 100644 --- a/api/docTextRunner/runner_test.go +++ b/api/docTextRunner/runner_test.go @@ -53,7 +53,7 @@ func TestDocCleanRunner(t *testing.T) { ID: uuid.New(), } bodyBytes, err := json.Marshal(doc) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, @@ -82,8 +82,11 @@ func TestDocCleanRunner(t *testing.T) { pgxmock.NewRows([]string{"id", "documentId", "bucket", "key", "version", "mimetype", "fail"}). AddRow(cleanId, database.MustToDBUUID(doc.ID), &inloc.Bucket, &inloc.Key, int64(1), dbmimetype, repository.NullCleanfailtype{}), ) - pool.ExpectExec("name: AddDocumentTextEntry :exec").WithArgs(pgxmock.AnyArg(), inloc.Bucket, inloc.Key, cleanId). - WillReturnResult(pgxmock.NewResult("", 1)) + pool.ExpectQuery("name: AddDocumentTextEntry :one").WithArgs(pgxmock.AnyArg(), inloc.Bucket, inloc.Key, cleanId). + WillReturnRows( + pgxmock.NewRows([]string{"id"}). + AddRow(database.MustToDBUUID(uuid.New())), + ) mockSQS.EXPECT(). SendMessage( diff --git a/api/queryService/api.gen.go b/api/queryAPI/api.gen.go similarity index 77% rename from api/queryService/api.gen.go rename to api/queryAPI/api.gen.go index da88e348..a95fefc6 100644 --- a/api/queryService/api.gen.go +++ b/api/queryAPI/api.gen.go @@ -1,7 +1,7 @@ -// Package queryservice provides primitives to interact with the openapi HTTP API. +// Package queryapi provides primitives to interact with the openapi HTTP API. // // Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.4.1 DO NOT EDIT. -package queryservice +package queryapi import ( "bytes" @@ -172,19 +172,37 @@ type DocClient struct { // Document The document properties. type Document struct { - // Bucket The bucket containing the document - Bucket string `json:"bucket"` + // ClientId The client external id + ClientId ClientID `json:"client_id"` + + // Fields The fields and the value for the document + Fields map[string]interface{} `json:"fields"` + + // Hash The document hash + Hash Hash `json:"hash"` // Id The document id. Id DocumentID `json:"id"` - - // Key The path to the document - Key string `json:"key"` } // DocumentID The document id. type DocumentID = openapi_types.UUID +// DocumentSummary The document summary properties. +type DocumentSummary struct { + // Hash The document hash + Hash Hash `json:"hash"` + + // Id The document id. + Id DocumentID `json:"id"` +} + +// ErrorMessage Description of error +type ErrorMessage struct { + // Message Message describing the cause. + Message string `json:"message"` +} + // ExportDetails Payload for export trigger response. type ExportDetails struct { // ClientId The client external id @@ -233,6 +251,9 @@ type FieldFilter struct { // FieldFilterCondition The possible field filtering conditions. type FieldFilterCondition string +// Hash The document hash +type Hash = string + // IdMessage A single uuid. type IdMessage struct { // Id Unique identifier for entity. @@ -240,7 +261,7 @@ type IdMessage struct { } // ListDocuments The documents in the client. -type ListDocuments = []Document +type ListDocuments = []DocumentSummary // ListQueries A set of queries. type ListQueries struct { @@ -323,6 +344,18 @@ type RequiredQueryIDs = []QueryID // Version The desired version. type Version = int32 +// InternalError Description of error +type InternalError = ErrorMessage + +// InvalidRequest Description of error +type InvalidRequest = ErrorMessage + +// TooManyRequests Description of error +type TooManyRequests = ErrorMessage + +// Unauthorized Description of error +type Unauthorized = ErrorMessage + // CreateClientJSONRequestBody defines body for CreateClient for application/json ContentType. type CreateClientJSONRequestBody = ClientCreate @@ -370,6 +403,9 @@ type ServerInterface interface { // Get client sync status // (GET /client/{id}/status) GetStatusByClientId(ctx echo.Context, id ClientID) error + // Get document details by its id + // (GET /document/{id}) + GetDocument(ctx echo.Context, id DocumentID) error // Check export state. // (GET /export/{id}) ExportState(ctx echo.Context, id ExportID) error @@ -417,6 +453,8 @@ func (w *ServerInterfaceWrapper) GetClient(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } + ctx.Set(PlaceholderAuthScopes, []string{}) + // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetClient(ctx, id) return err @@ -530,6 +568,24 @@ func (w *ServerInterfaceWrapper) GetStatusByClientId(ctx echo.Context) error { return err } +// GetDocument converts echo context to params. +func (w *ServerInterfaceWrapper) GetDocument(ctx echo.Context) error { + var err error + // ------------- Path parameter "id" ------------- + var id DocumentID + + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) + } + + ctx.Set(PlaceholderAuthScopes, []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetDocument(ctx, id) + return err +} + // ExportState converts echo context to params. func (w *ServerInterfaceWrapper) ExportState(ctx echo.Context) error { var err error @@ -660,6 +716,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/client/:id/documents", wrapper.ListDocumentsByClientId) router.POST(baseURL+"/client/:id/export", wrapper.TriggerExport) router.GET(baseURL+"/client/:id/status", wrapper.GetStatusByClientId) + router.GET(baseURL+"/document/:id", wrapper.GetDocument) router.GET(baseURL+"/export/:id", wrapper.ExportState) router.GET(baseURL+"/query", wrapper.ListQueries) router.POST(baseURL+"/query", wrapper.CreateQuery) @@ -672,60 +729,68 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xbaXMjt9H+Kyi8/mbeh0jprXyQpbWLyUa7WWlTTnYVFjjTJGEPZygAI4ne4n9P4ZoT", - "Qw654tou5ZsoXI3uBw8a3T1fsBet1lEIoeD44gteAvGBqT8/EAFv6YoK+cMH7jG6FjQK8YVqQoFsQzSc", - "R2xFZAOiIdI/0GesWv//iYZ+9PQXQVfQ1H9/xriB4Zms1gHgC9ztdGynsw5uYO4tYUXkiivy/BbChVji", - "i36vgddECGBy8f986jTP77+3w/Sv73ADi81aTskFo+ECb7dbOYqRFQizo6uAQigm1+UN3S0BeaoVTa5b", - "uIGp/O+aiCVu4JCs5LzUxw3M4CGmDHx8IVgMWXm/YzDHF/j/2qlC27qVt5OFpUxvntcRq5QCVOtJpEgW", - "llL8Iwa2qRJico2iORJLQA+y28uLYldXRmLA11HIQdloEkozk+ANYxErS2ebEQf2CAyB7CblqwKuSwrT", - "t512VHJMwkcSUP8DPMTAhWtt1Y6Y7oBmkb95kaW3Vm0ZlF6R8HYTeg4ptGEMWilHJAiiJxouEPEEfQTE", - "N6HH0+Mwi6IASIi3DTszAyLAbfg1i9bABAUuTzLyZFcahXKXaZMcSv36mLeAqdP/RvbUoLC4+qSBpua4", - "T7YVzX4BT6S72nOq4dngRs2V8s/l5SVu5LjmLMc1LRezpGv+EPmbnetS/+t0V9ZEtQpujJYrhVEqzO+e", - "gYC8AnrDAzRwK4iIeXnR2zV4dC5hJLHKVS9JKcSIIpUCYbySe5rcTG//dXOFG/jm3Z3688115sfk5qfM", - "nt0CuM1wafdt1s9eVVp3ZdvwZEP77WM2X7SRmaLaTh/3YJVajotD+hBDEbKd7vlwPOx7zfHc95ujkec3", - "Z/0zr9kbDnuD7sz3/X4fN7DeK77AcawmKGC8Qp8f134dchBLItCKbNAMUKyGOHDukXDKDYft16YlvOPo", - "oqzqyId/AuNKfNdufODSYsiLfECPumcrqzcairOBVhxdSaie93r9/qjX6Z+Nh4PR6KzT6TTwioa6tZsI", - "Ie23AKalCALwhOsmS5rQKvIhKKtP0/n0Md3ELn3YvW4bWMNoehhFzykE/n7gW6F/1N23DRwQAVwcIabR", - "3NST1xOwujNkDZuZRcCzOGqKwulNlZfopFrUiuVLSmkUjekkh5xu3aBVEhVvaeUO2MFlHNU6Tbm19alq", - "YOX81cBR6s3ldWnum2Sa/buuvsKiWKxjYRQgJ27tvrY+keZvl81/31fcXgUcVytbXhtlDVMBqwMPiwIr", - "eZ7okUpcIxZhjGxyUt2Cw/18TzZBRHxlcsW5yudDV9WWP5pBjiaDP86ZLgHtOvI03+293Ap+ygtdaqf1", - "mBs4rrvAR7dfqWdo2EOb7PPerct4ValK37RmdFrW4yz2foWKCXQb8qJQEBpKmIvMtEe5q/uVY/ek9f8r", - "VPj18gmMRLRLos5gXBCp7ZTKZQOjFi3ALtVX+ZCJ8vXLo+A2dvx5c9afj5uj/mDcPCezbrMLw+GsP++O", - "wR8d4TbqoMI1CEIDvpu0TGhDMLpYAEP22e84Y8c4MPqCmAaRR0Sl02dbJak/Lam3VHY0gv1G12hOA0BP", - "NAikZzuP4rCgRd6/aLfJzGtfXrZ7nd6w0+v220q1I+I1O6P+rDnqnI+b40HvrDkj/vmoMx9756NBy+OP", - "e3Ci5lZgaaug1pfxtt36/vNnOdQJ6nqPFW2hisdK1t3Z8XCpFbOqQBw0B/6w2xx1+17zfAzQHJwNYNwf", - "d7vzbv9oxFW9PNUZjTinsyARTG5Mc5B9c0o1BSDAV5Gt6ZpFCwZcunpzQgPwnS9OvfCdhu9uqBuMqxs6", - "NGKUca6u2emcBjZAmZ/wR9WgX9BetAY0Ixx8FIXGCzIu0SMJYr27Wl6Juqz11DVcEhougEt5jhEzGYzS", - "OGxZCxD60+pHZ0C4QLJZXsvJhLmHmmxtCroqBDL6PfeRYaJyOcrRnLIXXLDsiLhck6xJKtSrfT0vCuJV", - "WObLKPSpqOEkZRa6SsZYf296/ENBQ9BtQN2GYg7zOLA3pwZTDrOH3+kpdLvyJZ6HboHnMjtsZPSViH6/", - "2yxXWQ3vIBx9MOeJyZKVcuwTAOdTsSRy/YWKxjL70wsiDv5UhYAeSYAbOFpDmP0dwFxMy90YXSxd/6eh", - "F8S+Dvvpv1zUNvH/DpyTBbiiaJyGiwCQpOeqYGZ+yEcbt4JQ0DkFpq//UFCxaR3M+PVCoG8pF9Y34rtd", - "o/RJl/j4tZgz8Xr306aURr6KqetUXCIOQrLLg+5RVupD1VA5b2FkLdHVCz0v97Db23NmrBQudesJHVsL", - "ogX1UBxSJSc8gxe7MwjHh7eicE4XtXZ8pbvW8v+TIMZXhLSs9qYZA+4a+sH0N2urJ7RWdQ1Z72RH5yNC", - "TVGKOZX2VWnXq0TDxZCl/H/MtAttQ09JinCXb/v58xfpym6dRK4X3ZWWStwHZDcrbxKVngJEUhFK9+Lh", - "SPn9bahGVxqnyglXOqh+9cH8bNgcnY3OmmMfzpvng0F/SM77/f6IHOGDa+GBi8pkqSObaOyEJAhtErVs", - "NMvS00Of7DrMeOihLeg+u3pxykqTaEXo16xbE/ati+YsWuUUUVaA8kgcNRfA40Dk8vLJBLujD/tDD3rJ", - "6v0ZOO/K8cmRpaIB6/D89fbdzfTNz3cfLq/u3n3ADXz17ubuzc930x8/vn3rdEjUuscno7J4+72vnq8n", - "FNebodSr0ldIGFNjZnJ9oNugT9ceh6dWqq0iy9bvZbNsve5gNBj3zwajTHKtU06uyccceDGjYnMrxdWK", - "XQfEg2UU+MAuY3keSq/0tAOy45HaLyjQzGMRM0BU8qckAmLeCar+RVdvpBUwPzcv30+af4NNesLImsrf", - "qqiDhvPI4SO9nySuaP4mVepG75i3BC7MLcuBPVJPu3qCCkXqrn6X7yfyNWPNgDutTqur4mJrCMma4gvc", - "b3VafazIYamU1faSgPg6cpG4vpM5IiiEJ5uefqJCh83WLHqkPvjI19G/ln6taIEmfjLehN31SQAubLbe", - "i0JhlifrdUB1aK79C9c4OqS0yjgPSusu/Cn53L6Dl5UurWQq1iX1Ot0XltlUjzhk1u1GRB/x2POA83kc", - "BJsXKnUadDpVI5Jdtwv1UNsGHtYblq3gyp5TfPHJcUI/3W/vG5jHqxWRTwoDmhzmJPbJgsurxJRe6FOB", - "7+X0BsbtL9TfSvEWrrzCBxCMwqMCM9c3l2cRPdsgKripucsj+CcQGfjm8NB5MTykqalqMGTO2J/P/olt", - "fwKRHDmp9sn1DtPmyzc/uddNu2SyAfeK5DwH/WuXguuoLOUqh5rlNYm5SjrTg78BnRnHZw+dici4OzXI", - "q+Mgd71t6zG9MpbRKs7yf02GaXvZmp4DuCap9zF0k6s3LrOO7f7DxuDaPyUFpYVKLgpKRP9Ts9BB+DBM", - "lTVaYrAsWNKSjVPS1i0Iu3wq0n7Cuq3G0QmoK1u9sp+6ZqDCoM4Cpn1sNthVTidnfWVkdpsH6258FvnM", - "z0bN9/CZtFRg3pVpOH22yZakuwgtF53/NoyWTwjscKySbciNvQKwqLiAyOVDdLSkdBMm6nsRciviTmfF", - "1ePzK/gycn+pQQVVfl6mvGPNIskJZXCajL5O75+IHPO1AxXsaAQ17Kc03/qmD9M0DeiQ8E2ufOf1eYzG", - "eGlBR+akmJqUSo5NK3VqECzfhJ79ZqGWr2g+gvg2jmLxs4tqZjVbeF0+o/3kJLXhaV64EmEahrvjHldL", - "8H7VuPJixqxdVKw+V5qUR1VaZAWnRFO+erCadJaEoxlAiJLCrdcQCJOmy9WwtXZQzqFYSr8GVVh6sAn9", - "vS/aIF+DkK1KU4VgHqMCGCVuL9BWRZzY87PLOCB1WdzBa/H5HhLVWwypREIOQjXSADqNdHAWQFeMnMa7", - "yhYQHJMDeMjI9gfwtHR+53/h/6fEMBWATYjriNi/hvHu0H+K2RNRlanLqoLAawu3JTbJxdjKLHXQRZck", - "sQ/LCmRorkZS4OTstjsloIP4ttbWxtRs3j0pgzgiS6CB+NqTBAfxUFuYiqivwKnzHn6jqikVjekaqjjU", - "H6tVXcn5svtC1AO4ODlqsyViFdAt1IQdEvjonEJYU8blklbLyOPgNYQJ1W73I1/Nyx4txgvFNizyYy+p", - "Y1GlMzEL8AVeCrHmF+22H3m/bVpetGo/dhXyzTrFmd5Z7EoPLlBcJB049R7maUFO/oG9bdScxgbJszMV", - "A+d1J0vD6clcpThq3blSj93MlNN+3Vn0CzIzS/7puL3f/jcAAP//x4FEowZKAAA=", + "H4sIAAAAAAAC/+xc63PbRnD/V27QfGr4JiVS6nSmjOQ4bG3ZkeROOpbKOQJL8lIAR90dJDMe/u+de+EN", + "EqRJJR804w8CcY/dvd3f7u0u/N1xabCiIYSCO5ffnSVgD5j68xYL+EACIuSDB9xlZCUIDZ1L9Qr58h0i", + "4ZyyAMsXiIRIP6AHR739txcSevTl3wUJoKn/fnCchgPfcLDywbl0up2OHdTtOA2Hu0sIsNyxdMy5HBPg", + "bx8gXIilc9nvNZwVFgKYJOt/v3aaF48/28H66Sen4Yj1Si7EBSPhwtlsNnIWwwEIw+uVTyAUk+siq/dL", + "QK56iybXLafhEPnrCoul03BCHMh1iec0HAZPEWHgOZeCRZDm5CcGc+fS+Zd2Iuq2fsvb8caSpmvqRsEW", + "Ojzz/iSUpDaXtLz7tqKskhJQb09CR7yxpOL3CNi6iojJNaJzJJaAnuSw45Nid1cKw4CvaMhB6csklCqH", + "/XeMUSZ/cGkoIFSmglcrn7jKItp/cknt97qsy9U+Aud4AXrTLNN2V8SBPQNDIMdLtqustmwzM7adDFQ7", + "TcJn7BPvFp4i4OIVWVLbIqb3RTPqrY/E0T2lH3G4NhzxV2Pp1igKilY0RIJSFOBwbTnkR+Cu4dyCYOvm", + "eC6AFW3jJgpmwKRtcHBp6HE0gzllgARbk3CB8AKTsJWG4W6vk7YJDeLSdkLR72nEJUEUOJej80Gn03AC", + "EurnToytJBSwACYFsmk4X0IciSVl5C9pc68t+JclhChKkXAUjdpYEaU8xhUO79ahWzyDiQYm4zkIR9j3", + "6YuSvivIMyC+Dl2euKYZpT7gUJ6tWZkBFlAOfCtGV8AEAS79LXLlUELVkSav5FTi1fc/FjDrjL+RIzUo", + "Wlz9qoFWrfEYs0Vnf4IrEq52eFj4ZgBOrZVEAOPxOOf3zzN+v1Xm5ZM9f6Heeuu+xPsx2RUlUS2CGyPl", + "SmKUCLPcMxCQFUDvbA8J3AksIl7c9G4FLplLNZK6ytUoCRvYkKIwIpR2/tWZ3Ezv/ufmymk4N5/u1Z/v", + "rlMPk5v3KZ7LCSg/hrHl2+yfDii17Ipnw2OGdp+PYT5/RmaJ6nP6skNXiXXGUUieIsirbKd7cTY667vN", + "0dzzmsOh6zVn/XO32Ts76w26M8/z+n2nkUBtFKkFcjpeIc8vK68OOIglFijAazSTzkhOKdFzF4dTbjBs", + "tzQt4B0GF0VRUw/+Gxgn2g+UhLzA5Ykhl3qAnvXIVlpuJBTng7SLuuj1+v1hr9M/H50NhsPzTsZhdYsO", + "S1Lh++AKWuJL41cooB74RfFpOJ8+J0xsk4flddNwtBpN94PoOQHf2634luhf9fBNw/GxAC4OINNIbupK", + "9wSs7grpg02tIuCbOGiJnPUmwotlUk1qxfYFoTTyh1kKDhnZliutoijvpVU4YCcX9aiWNWX21lbVcNTl", + "p4YeJbeZrCyNv4mX2c11tQujkVhFwghALtw6zG3lFLhaytJfFEVLBAR7WonSUvxtomcqOg1ZmDG8zlB1", + "ByU5kc947VPsqbNWYKuCPXRVfeQHQ8fBKPDPMeaChl1TVwPdTq+WC1CO5M1OGyo3nKjuBl/KA0q9QsNa", + "a8znY7ksVSpnRxYpkVyJHH/MO1VaKw49Za7P2I8gxkVLUjqC+m4pWndjbNDTEmLXPedy0Ese+za/Y384", + "cy6/dhu9Rv+xTOeWmC938febHFNLP3IJtML5pX2W2jkW2LYz3JkL1HeXXODZ8ebNWX8+ag77g1HzAs+6", + "zS6cnc368+4IvOEBgael5y4KAszWO4jietRWFXtd6avdygSdySoUuLpOniTwqIxbVksDO9VZ0wgFEZdX", + "A9ePPEAY2ZebPPNB1YaGEqR/nUmlV+4NRxyyBx1vtyDPgAJAC0q99PXpANebk5ylslRuKk97DQITn293", + "hyZbLBhZLIAhm0k9EuromGPqU51UKtdM+1aGCy9L4i6VVA1hf5EVmhMf0AvxfXlZmtMozJkV71+223jm", + "tsfjdq/TO+v0uv22srUhdpudYX/WHHYuRs3RoHfenGHvYtiZj9yL4aDl8ufcSXQGo8xRqLVbP8t/qmbx", + "fbRpt35+eJBTS+OjevdffUIV9980Gm25C9cqA1RAEDQH3lm3Oez23ebFCKA5OB/AqD/qdufdQ+6+GX7K", + "owTKOZn5MWGSMQ09No0hxeSDAE8VC6YrRhcMuLw9zDHxwStNYuiN77X6bld1o+Mq9gsNGUU9V7g/nRPf", + "1p+yC/6qXuikjEtXgGaYg4doaAJrE2UrZ8hrx7sqDNRL1wh2SbgALuk5hMx4MkrKbEUpQOhNq/MYPuYC", + "ydcSd+MFM3d/+bYpSADFomCZyTBRuR3haE7YETcshhtlAUj6SCrEq28RLvWjICziJQ09ImqE36mNruI5", + "NmKbHn731CpYfoD6HYo4zCMfCaoURStTRmf3vx4mqtvtdPKqm8O5FIeNlLxi0h+3H8tVWsJbAEcb5jw+", + "sninDPr4wPlULLHcf6ES/Mw+uj7l4E1VVvEZ+07DoSsI088+zMW0OIyRxbLsdxOEKGDWf5VB228mCNsS", + "y5lYdZsDqziniVcZV40RJ+HCBySxvyr5np3yxeZZIRRkToDp2CIURKxbe7uTein7D4QLG1ny7XJKMhHx", + "1bQWLOcD693QLIn6PQJGyixvjDgIiWBPekRRtk9VU+W6uZm1OFCJpSzdZ93eDru0VJRJXS9YwppPF8RF", + "UUgUnfAN3Ki88HV4VpaGc7KoxfGVHlrrdhLn3n4gE2ulN00d4Lapt2a82VslgLSoa9B6LweWXqTUEoVU", + "aYGvynO9iiWcz7TL3yOmw3SbGYg7O7bBz8PD99a/PjxsSkFIb7qtmhqHKMgyK72VqqrKO1xMQsH37q8p", + "f/8ZqtmVh1MV6CsZVKcaYH5+1hyeD8+bIw8umheDQf8MX/T7/SE+IM7XxAMXqWaUnUVwc05IKqHttSge", + "mgXr6X4JBZsd39doc7JP755fsvJItCD0jblcEvY+jeaMBhlBFAWgE2jFhj7gkS8y7VTxAns7/hzXestq", + "/ow6bytNy5mFXi8bVP3n3aeb6bs/7m/HV/efbp2Gc/Xp5v7dH/fTX798+FAa9Kh9D6+hpvXt73Y9Pw4o", + "ZfeSwqjKWCFGTK0zk+s9wwZtXTsCnloV4oricLZ/qdcdDAej/vlguKOJqeFwcCNGxPpOkqsFu/KxC0vq", + "e8DGkSiJmz8nA5CdjxS/Otc9j0TEABGJnxIIbJpOtS3qpqOkcfGP5vjzpPlfsE4sDK+IfFa9SCScU9ta", + "hV0FkhBg4juXThC4i4iEIXD+HxgzENByaZCs/JG4Sww++ui+N8OchhMxOdWj7l9rNbrQXjX+PImD3ayT", + "VieJPjF3CVwYB86BPRNXR5E+ccGgl6EgCs1vXrzzy8tLy7gWu78gQvmZsvXHnyfyEmc1w+m0Oq2uSgeu", + "IMQr4lw6/Van1XcUXi3V+bXduMK0omV+RYcJHGEUwott9HghQmcLV4w+Ew885OmkZ0tf0jRBEy+eb+pY", + "2jiBC9v3cpQmuEx3WEkTnDYJRV95OOOmqUt6YvMdrr1O98g0mz6sEpr1e0Oih3jkusD5PPL9Y/WCDjqd", + "qhkx1+1cC6ya1t09LdPrKCf1LnZPyjenbhrOWT0a043HaZxyLr+WINTXx81jw+G2aGM0NKPgEl7wgktX", + "ajqmtOk6j3J5YzPt78TbSPIWZbXvWxCMwLOyHK49t2vNZ7ZGRHDTKp41l/cgUraSUb7O0ZQvKSxXa17K", + "oN+U7XjK9h5EDDhSDybXW3Qt+0nG13LakiGpEtCjgni3xB/rGI/rVDzhqiUjjerSCCrBXE9+BTA3kegO", + "MBfUxJ81oLtT4to02zaEfcPY06m9Ps+0q62Jr2033Yi4B9LGTYoGbDMfLBUx1w7/ZW2MyDslACfdlWUA", + "HJP+hsGnxOC0hsTakdbMpLftlIB8B8Jun5C0G4rvqpX2BKCcbvPbDcozUBn30hbPXTg92NZwLFd9g+nT", + "WcZd1jK2G0Meqb10UWgHUku18E2+JKkWzdbpL4TKoDpTfHodrM7Wu7YEzDEbkrE3zTyuZqrkmsjUFnXK", + "sRBQxGd1FNjOK7luX1Hpkh/wBKWZlklIBFGxeaoPa8WoRLuiJZjWG92HcyLYzzb5VOC+IdTgupJ861VT", + "KUlJvYTCd5k+u7co/6RGajQlafNKmaXpVKv0Hkn/Xg3Xwdehaz+OqxXfm6/tXie4z3/fV+0zDAtvcf7J", + "4nz7IWWiMKfJt0h1tq6pbmJQpKJm9QVH3F9kdFoXlwvKfJ18GnDKFKHeo0R57bs3vT2d3no5GScqcdxQ", + "J13SV0qsgXu7Cl8twf0/rb9uxJhFMlWPzrT4ZlU3aVaGU6putgu/OiZYYo5mACGKG6DfFPnIlRWpJ5nG", + "89aWiGBf1U3+VxyluE+2Q25nktDPNvWlW8lV97bLiABGcPn107YZnvjKabcp0d9xnoM3vT3BZfMpPmer", + "sKrmPv480bpao1quG0D2LpbrXs/TXOnSrX+HlMqfUrT9A653ug3irUr+ylVyqwUllhFD8QHlcW0v26vj", + "iXGcCHxN63aVrr3FvCesycQKkCnEZHF3rxghbqjbryCeAu4a9fCT4/X2ariuX9tvi+Lvx00PYNySeUCB", + "XGv8W338FevjtZG1LUwb+A8YRGkI8059QqKAWTeOR6HOTlRFM9nvGXNZauDi5OaR7ouvsJFcI/w+ierO", + "KYg1vetl1GoaeeS/1ZCOnZ6Wot1uYmpN9myNKdfKzKgXuXErr2pM1o26SyFW/LLdjluF289dZWJmj/xK", + "n6yRyCjbV+gqg2yVTuRJU3I2P7lp1FzGlmrTK+XLt3UXS4q68VqFrFPdtZIblVkplnzdFXQqIbVCNoew", + "edz8fwAAAP//YgULir1ZAAA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/queryService/client.go b/api/queryAPI/client.go similarity index 89% rename from api/queryService/client.go rename to api/queryAPI/client.go index 36a28961..65713ed3 100644 --- a/api/queryService/client.go +++ b/api/queryAPI/client.go @@ -1,4 +1,4 @@ -package queryservice +package queryapi import ( "fmt" @@ -28,7 +28,7 @@ func (s *Controllers) CreateClient(ctx echo.Context) error { }) } -func (s *Controllers) GetClient(ctx echo.Context, id string) error { +func (s *Controllers) GetClient(ctx echo.Context, id ClientID) error { client, err := s.svc.Client.GetByExternalId(ctx.Request().Context(), id) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unable to get client: %s", err)) @@ -42,7 +42,7 @@ func (s *Controllers) GetClient(ctx echo.Context, id string) error { }) } -func (s *Controllers) UpdateClient(ctx echo.Context, id string) error { +func (s *Controllers) UpdateClient(ctx echo.Context, id ClientID) error { req := ClientUpdate{} if err := ctx.Bind(&req); err != nil { return echo.NewHTTPError(http.StatusBadRequest, err) diff --git a/api/queryService/client_test.go b/api/queryAPI/client_test.go similarity index 84% rename from api/queryService/client_test.go rename to api/queryAPI/client_test.go index cfdd9163..e1c6d0c9 100644 --- a/api/queryService/client_test.go +++ b/api/queryAPI/client_test.go @@ -1,4 +1,4 @@ -package queryservice_test +package queryapi_test import ( "encoding/json" @@ -8,13 +8,12 @@ import ( "strings" "testing" - queryservice "queryorchestration/api/queryService" + queryapi "queryorchestration/api/queryAPI" "queryorchestration/internal/client" "queryorchestration/internal/database" "queryorchestration/internal/database/repository" "queryorchestration/internal/serviceconfig" - "github.com/go-playground/validator/v10" "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/pashagolub/pgxmock/v3" @@ -30,16 +29,16 @@ func TestCreateClient(t *testing.T) { cfg.DBPool = pool cfg.DBQueries = repository.New(pool) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Client: client.New(cfg), }) - body := queryservice.ClientCreate{ + body := queryapi.ClientCreate{ Name: "example_name", Id: "external_id", } bodyBytes, err := json.Marshal(body) - assert.NoError(t, err) + require.NoError(t, err) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(bodyBytes))) @@ -53,7 +52,7 @@ func TestCreateClient(t *testing.T) { ) err = cons.CreateClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusCreated, rec.Code) assert.Equal(t, fmt.Sprintf("{\"id\":\"%s\"}\n", body.Id), rec.Body.String()) } @@ -66,7 +65,7 @@ func TestGetClient(t *testing.T) { cfg.DBPool = pool cfg.DBQueries = repository.New(pool) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Client: client.New(cfg), }) @@ -86,13 +85,13 @@ func TestGetClient(t *testing.T) { ) err = cons.GetClient(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) - var res queryservice.DocClient + var res queryapi.DocClient err = json.Unmarshal(rec.Body.Bytes(), &res) - assert.NoError(t, err) - assert.EqualExportedValues(t, queryservice.DocClient{ + require.NoError(t, err) + assert.EqualExportedValues(t, queryapi.DocClient{ Id: id, Uid: clientUid, Name: "client_name", @@ -108,16 +107,16 @@ func TestUpdateClient(t *testing.T) { cfg.DBPool = pool cfg.DBQueries = repository.New(pool) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Client: client.New(cfg), }) cs := false - body := queryservice.ClientUpdate{ + body := queryapi.ClientUpdate{ CanSync: &cs, } bodyBytes, err := json.Marshal(body) - assert.NoError(t, err) + require.NoError(t, err) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(bodyBytes))) @@ -145,7 +144,7 @@ func TestUpdateClient(t *testing.T) { pool.ExpectCommit() err = cons.UpdateClient(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.Empty(t, rec.Body.String()) } diff --git a/api/queryService/collector.go b/api/queryAPI/collector.go similarity index 96% rename from api/queryService/collector.go rename to api/queryAPI/collector.go index 2406ce0d..4eb7b620 100644 --- a/api/queryService/collector.go +++ b/api/queryAPI/collector.go @@ -1,4 +1,4 @@ -package queryservice +package queryapi import ( "fmt" @@ -10,7 +10,7 @@ import ( "github.com/labstack/echo/v4" ) -func (s *Controllers) GetCollectorByClientId(ctx echo.Context, clientId string) error { +func (s *Controllers) GetCollectorByClientId(ctx echo.Context, clientId ClientID) error { coll, err := s.svc.Collector.GetByClientExternalID(ctx.Request().Context(), clientId) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unable to get collector: %s", err)) @@ -36,7 +36,7 @@ func (s *Controllers) GetCollectorByClientId(ctx echo.Context, clientId string) }) } -func (s *Controllers) SetCollectorByClientId(ctx echo.Context, clientId string) error { +func (s *Controllers) SetCollectorByClientId(ctx echo.Context, clientId ClientID) error { req := CollectorSet{} if err := ctx.Bind(&req); err != nil { return echo.NewHTTPError(http.StatusBadRequest, err) diff --git a/api/queryService/collector_test.go b/api/queryAPI/collector_test.go similarity index 89% rename from api/queryService/collector_test.go rename to api/queryAPI/collector_test.go index 769bae09..3084ba76 100644 --- a/api/queryService/collector_test.go +++ b/api/queryAPI/collector_test.go @@ -1,4 +1,4 @@ -package queryservice_test +package queryapi_test import ( "encoding/json" @@ -8,7 +8,7 @@ import ( "strings" "testing" - queryservice "queryorchestration/api/queryService" + queryapi "queryorchestration/api/queryAPI" "queryorchestration/internal/collector" collectorset "queryorchestration/internal/collector/set" "queryorchestration/internal/database" @@ -18,7 +18,6 @@ import ( queuemock "queryorchestration/mocks/queue" "github.com/aws/aws-sdk-go-v2/service/sqs" - "github.com/go-playground/validator/v10" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" @@ -49,10 +48,10 @@ func TestSetCollector(t *testing.T) { av := int32(2) cv := int64(1) - body := queryservice.CollectorSet{ + body := queryapi.CollectorSet{ ActiveVersion: &av, MinimumCleanerVersion: &cv, - Fields: &[]queryservice.CollectorField{ + Fields: &[]queryapi.CollectorField{ { Name: "a", QueryId: uuid.New(), @@ -60,7 +59,7 @@ func TestSetCollector(t *testing.T) { }, } bodyBytes, err := json.Marshal(body) - assert.NoError(t, err) + require.NoError(t, err) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(bodyBytes))) @@ -68,7 +67,7 @@ func TestSetCollector(t *testing.T) { rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ CollectorSet: collectorset.New(cfg, &collectorset.Services{ Collector: collector.New(cfg), }), @@ -116,7 +115,7 @@ func TestSetCollector(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = cons.SetCollectorByClientId(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.Empty(t, rec.Body.String()) } @@ -134,7 +133,7 @@ func TestGetCollectorByclientId(t *testing.T) { ctx := e.NewContext(req, rec) svc := collector.New(cfg) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Collector: svc, }) @@ -153,18 +152,18 @@ func TestGetCollectorByclientId(t *testing.T) { ) err = cons.GetCollectorByClientId(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) - var res queryservice.Collector + var res queryapi.Collector err = json.Unmarshal(rec.Body.Bytes(), &res) - assert.NoError(t, err) - assert.EqualExportedValues(t, queryservice.Collector{ + require.NoError(t, err) + assert.EqualExportedValues(t, queryapi.Collector{ ClientId: id, MinimumCleanerVersion: coll.MinCleanVersion, MinimumTextVersion: coll.MinTextVersion, ActiveVersion: int32(1), LatestVersion: int32(2), - Fields: []queryservice.CollectorField{}, + Fields: []queryapi.CollectorField{}, }, res) } diff --git a/api/queryService/controllers.go b/api/queryAPI/controllers.go similarity index 72% rename from api/queryService/controllers.go rename to api/queryAPI/controllers.go index eade7a36..dd750bcf 100644 --- a/api/queryService/controllers.go +++ b/api/queryAPI/controllers.go @@ -1,4 +1,4 @@ -package queryservice +package queryapi import ( "queryorchestration/internal/client" @@ -9,11 +9,9 @@ import ( "queryorchestration/internal/query" querytest "queryorchestration/internal/query/test" queryupdate "queryorchestration/internal/query/update" - - "github.com/go-playground/validator/v10" ) -const Name = "queryService" +const Name = "queryAPI" type Services struct { Export *export.Service @@ -27,13 +25,11 @@ type Services struct { } type Controllers struct { - validator *validator.Validate - svc *Services + svc *Services } -func NewControllers(validator *validator.Validate, services *Services) *Controllers { +func NewControllers(services *Services) *Controllers { return &Controllers{ - validator: validator, - svc: services, + svc: services, } } diff --git a/api/queryAPI/controllers_test.go b/api/queryAPI/controllers_test.go new file mode 100644 index 00000000..c189b211 --- /dev/null +++ b/api/queryAPI/controllers_test.go @@ -0,0 +1,14 @@ +package queryapi_test + +import ( + "testing" + + queryapi "queryorchestration/api/queryAPI" + + "github.com/stretchr/testify/assert" +) + +func TestNewControllers(t *testing.T) { + cons := queryapi.NewControllers(&queryapi.Services{}) + assert.NotNil(t, cons) +} diff --git a/api/queryAPI/documents.go b/api/queryAPI/documents.go new file mode 100644 index 00000000..bff48154 --- /dev/null +++ b/api/queryAPI/documents.go @@ -0,0 +1,39 @@ +package queryapi + +import ( + "fmt" + "net/http" + + "github.com/labstack/echo/v4" +) + +func (s *Controllers) ListDocumentsByClientId(ctx echo.Context, clientId ClientID) error { + documents, err := s.svc.Document.ListByClientExternalId(ctx.Request().Context(), clientId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unable to list documents: %s", err)) + } + + docs := make([]DocumentSummary, len(documents)) + for i, doc := range documents { + docs[i] = DocumentSummary{ + Id: doc.ID, + Hash: doc.Hash, + } + } + + return ctx.JSON(http.StatusOK, docs) +} + +func (s *Controllers) GetDocument(ctx echo.Context, id DocumentID) error { + document, err := s.svc.Document.GetExternal(ctx.Request().Context(), id) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unable to list documents: %s", err)) + } + + return ctx.JSON(http.StatusOK, Document{ + Id: document.Id, + ClientId: document.ClientID, + Hash: document.Hash, + Fields: document.Fields, + }) +} diff --git a/api/queryAPI/documents_test.go b/api/queryAPI/documents_test.go new file mode 100644 index 00000000..04c4871d --- /dev/null +++ b/api/queryAPI/documents_test.go @@ -0,0 +1,121 @@ +package queryapi_test + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + + queryapi "queryorchestration/api/queryAPI" + "queryorchestration/internal/database" + "queryorchestration/internal/database/repository" + "queryorchestration/internal/document" + "queryorchestration/internal/serviceconfig" + "queryorchestration/internal/serviceconfig/queue/clientsync" + queuemock "queryorchestration/mocks/queue" + + "github.com/google/uuid" + "github.com/labstack/echo/v4" + "github.com/pashagolub/pgxmock/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestListDocumentsByClientId(t *testing.T) { + pool, err := pgxmock.NewPool() + require.NoError(t, err) + cfg := &struct { + serviceconfig.BaseConfig + clientsync.ClientSyncConfig + }{} + cfg.DBPool = pool + cfg.DBQueries = repository.New(pool) + mockSQS := queuemock.NewMockSQSClient(t) + cfg.QueueClient = mockSQS + + clientId := "clientid" + + e := echo.New() + req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("")) + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + rec := httptest.NewRecorder() + ctx := e.NewContext(req, rec) + + cons := queryapi.NewControllers(&queryapi.Services{ + Document: document.New(cfg), + }) + + ctx.Set("id", clientId) + doc := queryapi.ListDocuments{ + { + Id: uuid.New(), + Hash: "hash", + }, + } + + pool.ExpectQuery("name: ListDocumentsByClientExternalId :many").WithArgs(clientId). + WillReturnRows( + pgxmock.NewRows([]string{"id", "hash"}). + AddRow(database.MustToDBUUID(doc[0].Id), "hash"), + ) + + err = cons.ListDocumentsByClientId(ctx, clientId) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, rec.Code) + + var res queryapi.ListDocuments + err = json.Unmarshal(rec.Body.Bytes(), &res) + require.NoError(t, err) + assert.EqualExportedValues(t, doc, res) +} + +func TestGetDocument(t *testing.T) { + pool, err := pgxmock.NewPool() + require.NoError(t, err) + cfg := &struct { + serviceconfig.BaseConfig + clientsync.ClientSyncConfig + }{} + cfg.DBPool = pool + cfg.DBQueries = repository.New(pool) + mockSQS := queuemock.NewMockSQSClient(t) + cfg.QueueClient = mockSQS + + docId := uuid.New() + + e := echo.New() + req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("")) + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + rec := httptest.NewRecorder() + ctx := e.NewContext(req, rec) + + cons := queryapi.NewControllers(&queryapi.Services{ + Document: document.New(cfg), + }) + + ctx.Set("id", docId) + doc := queryapi.Document{ + Id: docId, + ClientId: "externalID", + Hash: "example", + Fields: map[string]interface{}{ + "json": "hello", + }, + } + + pool.ExpectQuery("name: GetDocumentExternal :one").WithArgs(database.MustToDBUUID(docId)). + WillReturnRows( + pgxmock.NewRows([]string{"id", "clientId", "hash", "fields"}). + AddRow(database.MustToDBUUID(doc.Id), "externalID", "example", []byte(`{"json": "hello"}`)), + ) + + err = cons.GetDocument(ctx, docId) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, rec.Code) + + var res queryapi.Document + err = json.Unmarshal(rec.Body.Bytes(), &res) + require.NoError(t, err) + assert.EqualExportedValues(t, doc, res) +} diff --git a/api/queryService/export.go b/api/queryAPI/export.go similarity index 50% rename from api/queryService/export.go rename to api/queryAPI/export.go index aa0af464..2ebc26d8 100644 --- a/api/queryService/export.go +++ b/api/queryAPI/export.go @@ -1,16 +1,15 @@ -package queryservice +package queryapi import ( "net/http" "github.com/labstack/echo/v4" - "github.com/oapi-codegen/runtime/types" ) -func (s *Controllers) TriggerExport(ctx echo.Context, clientId string) error { +func (s *Controllers) TriggerExport(ctx echo.Context, clientId ClientID) error { return ctx.JSON(http.StatusOK, map[string]string{"status": "export triggered"}) } -func (s *Controllers) ExportState(ctx echo.Context, id types.UUID) error { +func (s *Controllers) ExportState(ctx echo.Context, id ExportID) error { return ctx.JSON(http.StatusOK, map[string]string{"status": "export triggered"}) } diff --git a/api/queryService/export_test.go b/api/queryAPI/export_test.go similarity index 71% rename from api/queryService/export_test.go rename to api/queryAPI/export_test.go index b0542607..73f729d1 100644 --- a/api/queryService/export_test.go +++ b/api/queryAPI/export_test.go @@ -1,4 +1,4 @@ -package queryservice_test +package queryapi_test import ( "net/http" @@ -6,12 +6,12 @@ import ( "strings" "testing" - queryservice "queryorchestration/api/queryService" + queryapi "queryorchestration/api/queryAPI" - "github.com/go-playground/validator/v10" "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestTriggerExport(t *testing.T) { @@ -20,10 +20,10 @@ func TestTriggerExport(t *testing.T) { rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{}) + cons := queryapi.NewControllers(&queryapi.Services{}) err := cons.TriggerExport(ctx, "clientid") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.NotEmpty(t, rec.Body.String()) } @@ -34,12 +34,12 @@ func TestExportState(t *testing.T) { rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{}) + cons := queryapi.NewControllers(&queryapi.Services{}) id := uuid.New() err := cons.ExportState(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.NotEmpty(t, rec.Body.String()) } diff --git a/api/queryService/parse.go b/api/queryAPI/parse.go similarity index 99% rename from api/queryService/parse.go rename to api/queryAPI/parse.go index a5343ebb..7a9c5b79 100644 --- a/api/queryService/parse.go +++ b/api/queryAPI/parse.go @@ -1,4 +1,4 @@ -package queryservice +package queryapi import ( "errors" diff --git a/api/queryService/parse_test.go b/api/queryAPI/parse_test.go similarity index 91% rename from api/queryService/parse_test.go rename to api/queryAPI/parse_test.go index 80e3beb4..20149c2e 100644 --- a/api/queryService/parse_test.go +++ b/api/queryAPI/parse_test.go @@ -1,4 +1,4 @@ -package queryservice +package queryapi import ( "testing" @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/oapi-codegen/runtime/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseQueries(t *testing.T) { @@ -27,7 +28,7 @@ func TestParseQueries(t *testing.T) { }, } out, err := parseQueries(in) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, out, len(in)) assert.ElementsMatch(t, []Query{ { @@ -56,7 +57,7 @@ func TestParseQuery(t *testing.T) { Config: &cfg, } out, err := parseQuery(in) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, Query{ Id: in.ID, Type: CONTEXTFULL, @@ -78,7 +79,7 @@ func TestParseQueryMinimal(t *testing.T) { LatestVersion: 2, } out, err := parseQuery(in) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, Query{ Id: in.ID, Type: CONTEXTFULL, @@ -90,11 +91,11 @@ func TestParseQueryMinimal(t *testing.T) { func TestParseQueryType(t *testing.T) { qt, err := parseQueryType(resultprocessor.TypeContextFull) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, CONTEXTFULL, qt) qt, err = parseQueryType(resultprocessor.TypeJsonExtractor) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, JSONEXTRACTOR, qt) _, err = parseQueryType(resultprocessor.Type(-1)) @@ -103,11 +104,11 @@ func TestParseQueryType(t *testing.T) { func TestParseSpecQueryType(t *testing.T) { qt, err := parseSpecQueryType(CONTEXTFULL) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, resultprocessor.Type(resultprocessor.TypeContextFull), qt) qt, err = parseSpecQueryType(JSONEXTRACTOR) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, resultprocessor.Type(resultprocessor.TypeJsonExtractor), qt) _, err = parseSpecQueryType("invalid") @@ -118,12 +119,12 @@ func TestParseStringToUUIDArray(t *testing.T) { ids := []uuid.UUID{uuid.New()} out, err := parseStringToUUIDArray(&[]string{ids[0].String()}) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, ids, *out) _, err = parseStringToUUIDArray(&[]string{"invalid_uuid"}) assert.Error(t, err) out, err = parseStringToUUIDArray(nil) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, out) } diff --git a/api/queryService/query.go b/api/queryAPI/query.go similarity index 90% rename from api/queryService/query.go rename to api/queryAPI/query.go index e1f65f6c..aca963bc 100644 --- a/api/queryService/query.go +++ b/api/queryAPI/query.go @@ -1,4 +1,4 @@ -package queryservice +package queryapi import ( "fmt" @@ -8,7 +8,6 @@ import ( resultprocessor "queryorchestration/internal/query/result/processor" "github.com/labstack/echo/v4" - "github.com/oapi-codegen/runtime/types" ) func (s *Controllers) ListQueries(ctx echo.Context) error { @@ -27,7 +26,7 @@ func (s *Controllers) ListQueries(ctx echo.Context) error { }) } -func (s *Controllers) GetQuery(ctx echo.Context, id types.UUID) error { +func (s *Controllers) GetQuery(ctx echo.Context, id QueryID) error { query, err := s.svc.Query.Get(ctx.Request().Context(), id) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unable to get query: %s", err)) @@ -66,7 +65,7 @@ func (s *Controllers) CreateQuery(ctx echo.Context) error { }) } -func (s *Controllers) UpdateQuery(ctx echo.Context, id types.UUID) error { +func (s *Controllers) UpdateQuery(ctx echo.Context, id QueryID) error { req := QueryUpdate{} if err := ctx.Bind(&req); err != nil { return echo.NewHTTPError(http.StatusBadRequest, err) @@ -85,7 +84,7 @@ func (s *Controllers) UpdateQuery(ctx echo.Context, id types.UUID) error { return ctx.NoContent(http.StatusOK) } -func (s *Controllers) TestQuery(ctx echo.Context, id types.UUID) error { +func (s *Controllers) TestQuery(ctx echo.Context, id QueryID) error { req := QueryTestRequest{} if err := ctx.Bind(&req); err != nil { return echo.NewHTTPError(http.StatusBadRequest, err) diff --git a/api/queryService/query_test.go b/api/queryAPI/query_test.go similarity index 85% rename from api/queryService/query_test.go rename to api/queryAPI/query_test.go index 98e2944d..93814d07 100644 --- a/api/queryService/query_test.go +++ b/api/queryAPI/query_test.go @@ -1,4 +1,4 @@ -package queryservice_test +package queryapi_test import ( "encoding/json" @@ -8,7 +8,7 @@ import ( "strings" "testing" - queryservice "queryorchestration/api/queryService" + queryapi "queryorchestration/api/queryAPI" "queryorchestration/internal/collector" "queryorchestration/internal/database" "queryorchestration/internal/database/repository" @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/require" "github.com/aws/aws-sdk-go-v2/service/sqs" - "github.com/go-playground/validator/v10" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" @@ -41,15 +40,15 @@ func TestCreateQuery(t *testing.T) { cfg.DBPool = pool cfg.DBQueries = repository.New(pool) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Query: query.New(cfg), }) - body := queryservice.QueryCreate{ - Type: queryservice.CONTEXTFULL, + body := queryapi.QueryCreate{ + Type: queryapi.CONTEXTFULL, } bodyBytes, err := json.Marshal(body) - assert.NoError(t, err) + require.NoError(t, err) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(bodyBytes))) @@ -73,7 +72,7 @@ func TestCreateQuery(t *testing.T) { pool.ExpectCommit() err = cons.CreateQuery(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusCreated, rec.Code) assert.Equal(t, fmt.Sprintf("{\"id\":\"%s\"}\n", id), rec.Body.String()) } @@ -85,7 +84,7 @@ func TestListQueries(t *testing.T) { cfg.DBPool = pool cfg.DBQueries = repository.New(pool) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Query: query.New(cfg), }) @@ -102,17 +101,17 @@ func TestListQueries(t *testing.T) { ) err = cons.ListQueries(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) - var res queryservice.ListQueries + var res queryapi.ListQueries err = json.Unmarshal(rec.Body.Bytes(), &res) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, res.Queries) - assert.ElementsMatch(t, res.Queries, []queryservice.Query{ + assert.ElementsMatch(t, res.Queries, []queryapi.Query{ { Id: id, - Type: queryservice.CONTEXTFULL, + Type: queryapi.CONTEXTFULL, ActiveVersion: 1, LatestVersion: 2, }, @@ -126,7 +125,7 @@ func TestGetQuery(t *testing.T) { cfg.DBPool = pool cfg.DBQueries = repository.New(pool) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Query: query.New(cfg), }) @@ -145,15 +144,15 @@ func TestGetQuery(t *testing.T) { ) err = cons.GetQuery(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) - var res queryservice.Query + var res queryapi.Query err = json.Unmarshal(rec.Body.Bytes(), &res) - assert.NoError(t, err) - assert.EqualExportedValues(t, queryservice.Query{ + require.NoError(t, err) + assert.EqualExportedValues(t, queryapi.Query{ Id: id, - Type: queryservice.CONTEXTFULL, + Type: queryapi.CONTEXTFULL, ActiveVersion: 1, LatestVersion: 2, }, res) @@ -172,18 +171,18 @@ func TestUpdateQuery(t *testing.T) { cfg.QueueClient = mockSQS cfg.QueryVersionSyncURL = "here" - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ QueryUpdate: queryupdate.New(cfg, &queryupdate.Services{ Query: query.New(cfg), }), }) av := int32(2) - body := queryservice.QueryUpdate{ + body := queryapi.QueryUpdate{ ActiveVersion: &av, } bodyBytes, err := json.Marshal(body) - assert.NoError(t, err) + require.NoError(t, err) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(bodyBytes))) @@ -215,7 +214,7 @@ func TestUpdateQuery(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = cons.UpdateQuery(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) assert.Empty(t, rec.Body.String()) } @@ -230,7 +229,7 @@ func TestTestQuery(t *testing.T) { docsvc := document.New(cfg) col := collector.New(cfg) que := query.New(cfg) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Collector: col, Query: que, QueryTest: querytest.New(cfg, &querytest.Services{ @@ -242,7 +241,7 @@ func TestTestQuery(t *testing.T) { }), }) - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), } params := &result.Process{ @@ -250,12 +249,12 @@ func TestTestQuery(t *testing.T) { DocumentID: doc.ID, QueryVersion: int32(3), } - body := queryservice.QueryTestRequest{ + body := queryapi.QueryTestRequest{ DocumentId: params.DocumentID, QueryVersion: params.QueryVersion, } bodyBytes, err := json.Marshal(body) - assert.NoError(t, err) + require.NoError(t, err) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(bodyBytes))) @@ -280,13 +279,13 @@ func TestTestQuery(t *testing.T) { ) err = cons.TestQuery(ctx, params.QueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) - var res queryservice.QueryTestResponse + var res queryapi.QueryTestResponse err = json.Unmarshal(rec.Body.Bytes(), &res) - assert.NoError(t, err) - assert.EqualExportedValues(t, queryservice.QueryTestResponse{ + require.NoError(t, err) + assert.EqualExportedValues(t, queryapi.QueryTestResponse{ Value: "old_value", }, res) } diff --git a/api/queryService/status.go b/api/queryAPI/status.go similarity index 78% rename from api/queryService/status.go rename to api/queryAPI/status.go index fa9a11ae..24e320a3 100644 --- a/api/queryService/status.go +++ b/api/queryAPI/status.go @@ -1,4 +1,4 @@ -package queryservice +package queryapi import ( "fmt" @@ -7,7 +7,7 @@ import ( "github.com/labstack/echo/v4" ) -func (s *Controllers) GetStatusByClientId(ctx echo.Context, id string) error { +func (s *Controllers) GetStatusByClientId(ctx echo.Context, id ClientID) error { status, err := s.svc.Client.GetStatusByExternalId(ctx.Request().Context(), id) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unable to find client: %s", err)) diff --git a/api/queryService/status_test.go b/api/queryAPI/status_test.go similarity index 78% rename from api/queryService/status_test.go rename to api/queryAPI/status_test.go index 0e058c8e..bc2eade8 100644 --- a/api/queryService/status_test.go +++ b/api/queryAPI/status_test.go @@ -1,4 +1,4 @@ -package queryservice_test +package queryapi_test import ( "encoding/json" @@ -7,13 +7,12 @@ import ( "strings" "testing" - queryservice "queryorchestration/api/queryService" + queryapi "queryorchestration/api/queryAPI" "queryorchestration/internal/client" "queryorchestration/internal/database" "queryorchestration/internal/database/repository" "queryorchestration/internal/serviceconfig" - "github.com/go-playground/validator/v10" "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/pashagolub/pgxmock/v3" @@ -28,7 +27,7 @@ func TestGetClientStatus(t *testing.T) { cfg.DBPool = pool cfg.DBQueries = repository.New(pool) - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ + cons := queryapi.NewControllers(&queryapi.Services{ Client: client.New(cfg), }) @@ -50,13 +49,13 @@ func TestGetClientStatus(t *testing.T) { ) err = cons.GetStatusByClientId(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, http.StatusOK, rec.Code) - var res queryservice.ClientStatusBody + var res queryapi.ClientStatusBody err = json.Unmarshal(rec.Body.Bytes(), &res) - assert.NoError(t, err) - assert.EqualExportedValues(t, queryservice.ClientStatusBody{ - Status: queryservice.INSYNC, + require.NoError(t, err) + assert.EqualExportedValues(t, queryapi.ClientStatusBody{ + Status: queryapi.INSYNC, }, res) } diff --git a/api/queryRunner/runner_test.go b/api/queryRunner/runner_test.go index 54a12673..d014ce77 100644 --- a/api/queryRunner/runner_test.go +++ b/api/queryRunner/runner_test.go @@ -64,7 +64,7 @@ func TestQueryRunner(t *testing.T) { QueryID: uuid.New(), } bodyBytes, err := json.Marshal(doc) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, diff --git a/api/queryService/controllers_test.go b/api/queryService/controllers_test.go deleted file mode 100644 index 57dd25bb..00000000 --- a/api/queryService/controllers_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package queryservice_test - -import ( - "testing" - - queryservice "queryorchestration/api/queryService" - - "github.com/go-playground/validator/v10" - "github.com/stretchr/testify/assert" -) - -func TestNewControllers(t *testing.T) { - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{}) - assert.NotNil(t, cons) -} diff --git a/api/queryService/documents.go b/api/queryService/documents.go deleted file mode 100644 index 32071136..00000000 --- a/api/queryService/documents.go +++ /dev/null @@ -1,26 +0,0 @@ -package queryservice - -import ( - "fmt" - "net/http" - - "github.com/labstack/echo/v4" -) - -func (s *Controllers) ListDocumentsByClientId(ctx echo.Context, clientId string) error { - documents, err := s.svc.Document.ListByClientExternalId(ctx.Request().Context(), clientId) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unable to list documents: %s", err)) - } - - docs := make([]Document, len(documents)) - for i, doc := range documents { - docs[i] = Document{ - Id: doc.ID, - Bucket: doc.Bucket, - Key: doc.Key, - } - } - - return ctx.JSON(http.StatusOK, docs) -} diff --git a/api/queryService/documents_test.go b/api/queryService/documents_test.go deleted file mode 100644 index 20b292a6..00000000 --- a/api/queryService/documents_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package queryservice_test - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "strings" - "testing" - - queryservice "queryorchestration/api/queryService" - "queryorchestration/internal/database" - "queryorchestration/internal/database/repository" - "queryorchestration/internal/document" - "queryorchestration/internal/serviceconfig" - "queryorchestration/internal/serviceconfig/queue/clientsync" - queuemock "queryorchestration/mocks/queue" - - "github.com/go-playground/validator/v10" - "github.com/google/uuid" - "github.com/labstack/echo/v4" - "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestListDocumentsByClientId(t *testing.T) { - pool, err := pgxmock.NewPool() - require.NoError(t, err) - cfg := &struct { - serviceconfig.BaseConfig - clientsync.ClientSyncConfig - }{} - cfg.DBPool = pool - cfg.DBQueries = repository.New(pool) - mockSQS := queuemock.NewMockSQSClient(t) - cfg.QueueClient = mockSQS - - clientId := "clientid" - - e := echo.New() - req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("")) - req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) - rec := httptest.NewRecorder() - ctx := e.NewContext(req, rec) - - cons := queryservice.NewControllers(validator.New(), &queryservice.Services{ - Document: document.New(cfg), - }) - - ctx.Set("id", clientId) - doc := queryservice.ListDocuments{ - { - Id: uuid.New(), - Bucket: "bucketone", - Key: "keyone", - }, - } - - pool.ExpectQuery("name: ListDocumentsByClientExternalId :many").WithArgs(clientId). - WillReturnRows( - pgxmock.NewRows([]string{"id", "bucket", "key"}). - AddRow(database.MustToDBUUID(doc[0].Id), doc[0].Bucket, doc[0].Key), - ) - - err = cons.ListDocumentsByClientId(ctx, clientId) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, rec.Code) - - var res queryservice.ListDocuments - err = json.Unmarshal(rec.Body.Bytes(), &res) - assert.NoError(t, err) - assert.EqualExportedValues(t, doc, res) -} diff --git a/api/querySyncRunner/runner_test.go b/api/querySyncRunner/runner_test.go index 0c4e0883..b8f2324b 100644 --- a/api/querySyncRunner/runner_test.go +++ b/api/querySyncRunner/runner_test.go @@ -57,7 +57,7 @@ func TestQueryRunner(t *testing.T) { ID: uuid.New(), } bodyBytes, err := json.Marshal(doc) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, diff --git a/api/queryVersionSyncRunner/runner_test.go b/api/queryVersionSyncRunner/runner_test.go index b3aa9119..24b2949a 100644 --- a/api/queryVersionSyncRunner/runner_test.go +++ b/api/queryVersionSyncRunner/runner_test.go @@ -54,7 +54,7 @@ func TestQueryRunner(t *testing.T) { ID: uuid.New(), } bodyBytes, err := json.Marshal(doc) - assert.NoError(t, err) + require.NoError(t, err) body := string(bodyBytes) msg := &types.Message{ Body: &body, diff --git a/api/readme.md b/api/readme.md index 4cde9624..4c0aeb69 100644 --- a/api/readme.md +++ b/api/readme.md @@ -1,15 +1,18 @@ # Api related artifacts ## Prometheus metrics -Prometheus metrics are exposed for all api endpoints automatically at the standard `/metrics` endpoint. (http://localhost:8080/metrics) -## Swagger API documentation -Automatic API docs are generated and exposed for all routes at http://localhost:8080/swagger/index.html when the api server is running. +Prometheus metrics are exposed for all api endpoints automatically at the standard `/metrics` endpoint. (`http://localhost:8080/metrics`) + +## Swagger API documentation + +Automatic API docs are generated and exposed for all routes at `http://localhost:8080/swagger/index.html` when the api server is running. + +## Logging -## Logging Structured logging is built into all API routes automatically. -So for example here is a what a few API hits on queryService look like in the logs when using text (as opposed to json) +So for example here is a what a few API hits on queryAPI look like in the logs when using text (as opposed to json) ```bash ____ __ @@ -29,4 +32,4 @@ time=2025-02-05T13:38:39.807-08:00 level=INFO msg="HTTP request" method=GET uri= time=2025-02-05T13:38:39.871-08:00 level=INFO msg="HTTP request" method=GET uri=/swagger/doc.json status=200 latency=1.163167ms error= remote_ip=::1 time=2025-02-05T13:38:39.871-08:00 level=INFO msg="HTTP request" method=GET uri=/swagger/favicon-32x32.png status=200 latency=60.875µs error= remote_ip=::1 -``` \ No newline at end of file +``` diff --git a/cmd/queryService/main.go b/cmd/queryAPI/main.go similarity index 88% rename from cmd/queryService/main.go rename to cmd/queryAPI/main.go index 597a5e8b..492e546d 100644 --- a/cmd/queryService/main.go +++ b/cmd/queryAPI/main.go @@ -19,8 +19,6 @@ import ( "log/slog" "os" - "queryorchestration/internal/serviceconfig" - queryservice "queryorchestration/api/queryService" "queryorchestration/internal/client" "queryorchestration/internal/collector" @@ -31,7 +29,7 @@ import ( "queryorchestration/internal/query/result" querytest "queryorchestration/internal/query/test" queryupdate "queryorchestration/internal/query/update" - service "queryorchestration/internal/server/service" + "queryorchestration/internal/server/api" "queryorchestration/internal/serviceconfig/queue/clientsync" "queryorchestration/internal/serviceconfig/queue/queryversionsync" "queryorchestration/internal/serviceconfig/rbac" @@ -40,8 +38,8 @@ import ( _ "github.com/lib/pq" ) -type QueryServiceConfig struct { - service.BaseConfig +type QueryAPIConfig struct { + api.BaseConfig clientsync.ClientSyncConfig queryversionsync.QueryVersionSyncConfig } @@ -49,7 +47,7 @@ type QueryServiceConfig struct { func main() { ctx := context.Background() - cfg := &QueryServiceConfig{} + cfg := &QueryAPIConfig{} cfg.RegisterHandlersFunc = func() (*openapi3.T, error) { exp := export.New() @@ -72,7 +70,7 @@ func main() { Query: que, }) - services := &queryservice.Services{ + services := &queryapi.Services{ Export: exp, Collector: col, CollectorSet: colupdate, @@ -83,11 +81,11 @@ func main() { Document: doc, } - cons := queryservice.NewControllers(cfg.GetValidator(), services) + cons := queryapi.NewControllers(services) - queryservice.RegisterHandlers(cfg.Router, cons) + queryapi.RegisterHandlers(cfg.Router, cons) - swagger, err := queryservice.GetSwagger() + swagger, err := queryapi.GetSwagger() if err != nil { return nil, fmt.Errorf("error loading swagger: %s", err) } @@ -113,7 +111,7 @@ func main() { os.Exit(1) } - server, err := service.New(ctx, cfg) + server, err := api.New(ctx, cfg) if err != nil { slog.Error(err.Error()) os.Exit(1) diff --git a/database/migrations/00000000000102_job_views.down.sql b/database/migrations/00000000000102_document_views.down.sql similarity index 100% rename from database/migrations/00000000000102_job_views.down.sql rename to database/migrations/00000000000102_document_views.down.sql diff --git a/database/migrations/00000000000102_document_views.up.sql b/database/migrations/00000000000102_document_views.up.sql new file mode 100644 index 00000000..5493ded1 --- /dev/null +++ b/database/migrations/00000000000102_document_views.up.sql @@ -0,0 +1,200 @@ +CREATE OR REPLACE FUNCTION listDocumentIDs( + _clientId uuid, + _batchSize INTEGER, + _offset INTEGER +) +RETURNS TABLE (id uuid, totalCount BIGINT) AS $$ +DECLARE + totalCount BIGINT := 0; +BEGIN + SELECT COUNT(*)::BIGINT INTO totalCount FROM documents WHERE clientId = _clientId; + + RETURN QUERY + SELECT d.id, totalCount + FROM documents as d + WHERE d.clientId = _clientId + ORDER BY d.id + LIMIT _batchSize + OFFSET _offset; +END; +$$ LANGUAGE plpgsql; + +CREATE VIEW currentCleanEntries as +WITH RankedExtractions AS ( + SELECT + dc.id, + dc.documentId, + dc.bucket, + dc.key, + dc.mimetype, + dc.fail, + dce.version, + ROW_NUMBER() OVER (PARTITION BY dc.documentId ORDER BY dc.id DESC, dce.id DESC) as row_num + FROM documents d + JOIN currentCollectorMinCleanVersions ccv ON d.clientId = ccv.clientId + JOIN documentCleans dc ON dc.documentId = d.id + JOIN documentCleanEntries dce ON dc.id = dce.cleanId + AND dce.version >= ccv.minCleanVersion +) +SELECT + id, + documentId, + bucket, + key, + version, + mimetype, + fail +FROM RankedExtractions +WHERE row_num = 1; + +CREATE VIEW currentTextEntries as +WITH RankedExtractions AS ( + SELECT + dte.id, + cc.documentId, + dte.bucket, + dte.key, + dte.version, + dte.cleanEntryId, + ROW_NUMBER() OVER (PARTITION BY cc.documentId ORDER BY dte.id DESC) as row_num + FROM documents d + JOIN currentCleanEntries cc on cc.documentId = d.id + JOIN currentCollectorMinTextVersions ctv ON ctv.clientId = d.clientId + JOIN documentTextExtractions dte ON dte.cleanEntryId = cc.id + AND dte.version >= ctv.minTextVersion +) +SELECT + id, + documentId, + bucket, + key, + version, + cleanEntryId +FROM RankedExtractions +WHERE row_num = 1; + +CREATE VIEW currentClientCanSync as +WITH RankedExtractions AS ( + SELECT + ccs.clientId, + ccs.canSync, + ROW_NUMBER() OVER (PARTITION BY ccs.clientId ORDER BY ccs.id DESC) as row_num + FROM clients c + JOIN clientCanSync ccs on c.id = ccs.clientId +) +SELECT + c.id as clientId, + coalesce(r.canSync, false) as canSync +FROM clients c +LEFT JOIN RankedExtractions r on r.clientId = c.id and r.row_num = 1; + +CREATE VIEW fullClients as +SELECT c.id, c.externalId, c.name, cs.canSync + FROM clients as c + JOIN currentClientCanSync as cs on cs.clientId = c.id; + +CREATE OR REPLACE FUNCTION listValidDocumentResults(doc_id uuid) +RETURNS TABLE (documentId uuid, queryId uuid, resultId uuid, value text) AS $$ +DECLARE + count_before INT; + count_after INT; + iterations INT := 0; +BEGIN + CREATE TEMPORARY TABLE allResults AS + WITH + docs AS ( + SELECT id as documentId, hash, clientId + FROM documents + WHERE id = doc_id + ), + query_dependency_tree AS ( + WITH RECURSIVE query_deps AS ( + SELECT + q.queryId, + unnest(q.requiredIds) AS requiredId + FROM collectorQueryDependencyTree AS q + JOIN docs AS d ON d.clientId = q.clientId + WHERE array_length(q.requiredIds, 1) > 0 + + UNION ALL + + SELECT + qd.queryId, + unnest(q.requiredIds) AS requiredId + FROM query_deps qd + JOIN collectorQueryDependencyTree q ON qd.requiredId = q.queryId + WHERE array_length(q.requiredIds, 1) > 0 + ) + SELECT + query_deps.queryId, + array_agg(DISTINCT requiredId) AS all_required_ids + FROM query_deps + GROUP BY query_deps.queryId + ), + docResults AS ( + SELECT + d.documentId, + q.queryId, + r.id AS resultId, + r.value, + q.requiredIds as directRequiredIds, + COALESCE(qdt.all_required_ids, ARRAY[]::uuid[]) AS allRequiredIds + FROM docs AS d + JOIN collectorQueryDependencyTree AS q ON q.clientId = d.clientId + LEFT JOIN query_dependency_tree qdt ON q.queryId = qdt.queryId + LEFT JOIN currentTextEntries AS tte ON tte.documentId = d.documentId + LEFT JOIN results AS r + ON q.queryId = r.queryId + AND r.queryVersion = q.queryVersion + AND tte.id = r.textEntryId + WHERE r.value is not null + ) + SELECT * FROM docResults dr; + + CREATE TEMPORARY TABLE finalResults AS + SELECT * from allResults where array_length(directRequiredIds, 1) is null; + + SELECT COUNT(*) INTO count_before FROM finalResults; + RAISE NOTICE 'Starting with % rows', count_before; + + LOOP + iterations := iterations + 1; + + INSERT INTO finalResults + SELECT dr.* + FROM allResults dr + WHERE + dr.directRequiredIds IS NOT NULL + AND NOT EXISTS ( + SELECT 1 + FROM unnest(dr.directRequiredIds) AS req_id(queryId) + WHERE NOT EXISTS ( + SELECT 1 + FROM allResults req_dr + WHERE req_dr.queryId = req_id.queryId + AND req_dr.resultId IN (SELECT fr.resultId FROM finalResults fr) + AND exists ( + select 1 from resultDependencies rrd + where dr.resultId = rrd.resultId + and req_dr.resultId = rrd.requiredResultId + ) + ) + ) + and dr.resultId NOT IN (SELECT fr.resultId FROM finalResults fr); + + GET DIAGNOSTICS count_after = ROW_COUNT; + RAISE NOTICE 'Iteration %: Additional Entries %', + iterations, count_after; + + IF count_after = 0 THEN + EXIT; + END IF; + END LOOP; + + RETURN QUERY SELECT tr.documentId, tr.queryId, tr.resultId, tr.value + FROM finalResults tr; + + DROP TABLE finalResults; + DROP TABLE allResults; +END; +$$ LANGUAGE plpgsql; diff --git a/database/migrations/00000000000102_job_views.up.sql b/database/migrations/00000000000102_job_views.up.sql deleted file mode 100644 index 70ada117..00000000 --- a/database/migrations/00000000000102_job_views.up.sql +++ /dev/null @@ -1,95 +0,0 @@ -CREATE OR REPLACE FUNCTION listDocumentIDs( - _clientId uuid, - _batchSize INTEGER, - _offset INTEGER -) -RETURNS TABLE (id uuid, totalCount BIGINT) AS $$ -DECLARE - totalCount BIGINT := 0; -BEGIN - SELECT COUNT(*)::BIGINT INTO totalCount FROM documents WHERE clientId = _clientId; - - RETURN QUERY - SELECT d.id, totalCount - FROM documents as d - WHERE d.clientId = _clientId - ORDER BY d.id - LIMIT _batchSize - OFFSET _offset; -END; -$$ LANGUAGE plpgsql; - -CREATE VIEW currentCleanEntries as -WITH RankedExtractions AS ( - SELECT - dc.id, - dc.documentId, - dc.bucket, - dc.key, - dc.mimetype, - dc.fail, - dce.version, - ROW_NUMBER() OVER (PARTITION BY dc.documentId ORDER BY dc.id DESC, dce.id DESC) as row_num - FROM documents d - JOIN currentCollectorMinCleanVersions ccv ON d.clientId = ccv.clientId - JOIN documentCleans dc ON dc.documentId = d.id - JOIN documentCleanEntries dce ON dc.id = dce.cleanId - AND dce.version >= ccv.minCleanVersion -) -SELECT - id, - documentId, - bucket, - key, - version, - mimetype, - fail -FROM RankedExtractions -WHERE row_num = 1; - -CREATE VIEW currentTextEntries as -WITH RankedExtractions AS ( - SELECT - dte.id, - cc.documentId, - dte.bucket, - dte.key, - dte.version, - dte.cleanEntryId, - ROW_NUMBER() OVER (PARTITION BY cc.documentId ORDER BY dte.id DESC) as row_num - FROM documents d - JOIN currentCleanEntries cc on cc.documentId = d.id - JOIN currentCollectorMinTextVersions ctv ON ctv.clientId = d.clientId - JOIN documentTextExtractions dte ON dte.cleanEntryId = cc.id - AND dte.version >= ctv.minTextVersion -) -SELECT - id, - documentId, - bucket, - key, - version, - cleanEntryId -FROM RankedExtractions -WHERE row_num = 1; - -CREATE VIEW currentClientCanSync as -WITH RankedExtractions AS ( - SELECT - ccs.clientId, - ccs.canSync, - ROW_NUMBER() OVER (PARTITION BY ccs.clientId ORDER BY ccs.id DESC) as row_num - FROM clients c - JOIN clientCanSync ccs on c.id = ccs.clientId -) -SELECT - c.id as clientId, - coalesce(r.canSync, false) as canSync -FROM clients c -LEFT JOIN RankedExtractions r on r.clientId = c.id and r.row_num = 1; - -CREATE VIEW fullClients as -SELECT c.id, c.externalId, c.name, cs.canSync - FROM clients as c - JOIN currentClientCanSync as cs on cs.clientId = c.id; - diff --git a/database/queries/client.sql b/database/queries/client.sql index 08efff02..768dfc4f 100644 --- a/database/queries/client.sql +++ b/database/queries/client.sql @@ -24,17 +24,19 @@ doc_clean_entries as ( SELECT d.id AS document_id, d.clientId as client_id, - cte.id AS clean_entry_id + cte.id AS clean_entry_id, + cte.fail as clean_fail FROM docs d LEFT JOIN currentCleanEntries cte ON cte.documentId = d.id - WHERE cte.id is null or cte.id is not null and cte.fail is null ), doc_text_entries AS ( -- Documents with their current text entries SELECT d.document_id, - cte.id AS text_entry_id + cte.id AS text_entry_id, + d.clean_entry_id, + d.clean_fail FROM doc_clean_entries d LEFT JOIN currentTextEntries cte ON cte.cleanEntryId = d.clean_entry_id @@ -51,6 +53,7 @@ required_results AS ( JOIN collectorQueryDependencyTree cqdt ON cqdt.clientId = d.client_id JOIN doc_text_entries dte ON dte.document_id = d.document_id and dte.text_entry_id IS NOT NULL + where d.clean_fail is null ), existing_results AS ( -- Valid results that exist @@ -87,15 +90,21 @@ SELECT ( OR -- Documents with no text entries - (NOT EXISTS (SELECT 1 FROM doc_text_entries WHERE text_entry_id IS NULL) + ( + NOT EXISTS ( + SELECT 1 FROM doc_text_entries + where clean_entry_id is null or + (clean_fail is null and text_entry_id is null) + ) - and + and - -- Documents with missing results - NOT EXISTS (SELECT 1 FROM missing_results) + -- Documents with missing results + NOT EXISTS (SELECT 1 FROM missing_results) - and + and - -- Documents with missing dependencies - NOT EXISTS (SELECT 1 FROM dependency_check)) + -- Documents with missing dependencies + NOT EXISTS (SELECT 1 FROM dependency_check) + )::bool )::bool as is_synced; diff --git a/database/queries/document.sql b/database/queries/document.sql index aa58f0a9..9b195348 100644 --- a/database/queries/document.sql +++ b/database/queries/document.sql @@ -1,25 +1,40 @@ --- name: GetDocument :one -SELECT id, clientId, hash FROM documents WHERE id = $1 LIMIT 1; +-- name: GetDocumentSummary :one +SELECT id, clientId, hash FROM documents WHERE id = $1; + +-- name: GetDocumentExternal :one +WITH +docs AS ( + SELECT id, hash, clientId + FROM documents + WHERE id = @documentId +), +namedResults AS ( + SELECT + q.name, + dd.id, + d.value + FROM currentCollectorQueries AS q + JOIN docs as dd on dd.clientId = q.clientId + LEFT JOIN listValidDocumentResults(@documentId) AS d + ON d.queryId = q.queryId and q.name is not null +) +SELECT + d.id, + c.externalId AS clientId, + d.hash, + COALESCE(jsonb_object_agg(r.name, r.value) FILTER (WHERE r.name IS NOT NULL), '{}') AS fields +FROM docs AS d +JOIN clients AS c ON c.id = d.clientId +LEFT JOIN namedResults AS r ON d.id = r.id +GROUP BY d.id, c.externalId, d.hash; -- name: ListDocumentsByClientExternalId :many WITH client as ( SELECT id from clients where externalId = @clientId -), -docs as ( - SELECT d.id - from documents as d - JOIN client as c on d.clientId = c.id -), -entries as ( - SELECT - de.documentId, - de.bucket, - de.key, - ROW_NUMBER() OVER (PARTITION BY de.documentId ORDER BY de.id DESC) as rowNumber - FROM docs d - JOIN documentEntries de on d.id = de.documentId ) -SELECT documentId as id, bucket, key from entries WHERE rowNumber = 1; +SELECT d.id, d.hash + from documents as d + JOIN client as c on d.clientId = c.id; -- name: CreateDocument :one INSERT INTO documents (clientId, hash) VALUES ($1, $2) RETURNING id; diff --git a/database/queries/text.sql b/database/queries/text.sql index f45aff88..cfa7a355 100644 --- a/database/queries/text.sql +++ b/database/queries/text.sql @@ -3,8 +3,8 @@ SELECT EXISTS( SELECT 1 FROM currentTextEntries WHERE documentId = @documentId ); --- name: AddDocumentTextEntry :exec -INSERT INTO documentTextExtractions (version, bucket, key, cleanEntryId) VALUES ($1, $2, $3, $4); +-- name: AddDocumentTextEntry :one +INSERT INTO documentTextExtractions (version, bucket, key, cleanEntryId) VALUES ($1, $2, $3, $4) returning id; -- name: GetTextEntryByDocId :one SELECT id, documentId, bucket, key, version, cleanEntryId diff --git a/deployments/compose.local.yaml b/deployments/compose.local.yaml index 23a978c7..78536803 100644 --- a/deployments/compose.local.yaml +++ b/deployments/compose.local.yaml @@ -185,9 +185,9 @@ services: networks: - server-network - query_service: + query_api: image: queryorchestration:latest - command: ["./queryService"] + command: ["./queryAPI"] depends_on: localstack: condition: service_healthy diff --git a/deployments/prometheus.allmetrics.yaml b/deployments/prometheus.allmetrics.yaml index 74fd2bae..d9267dc2 100644 --- a/deployments/prometheus.allmetrics.yaml +++ b/deployments/prometheus.allmetrics.yaml @@ -4,10 +4,10 @@ global: scrape_interval: 10s scrape_configs: - - job_name: "query_service" + - job_name: "query_api" static_configs: - targets: - - "query_service:8080" + - "query_api:8080" metrics_path: "/metrics" - job_name: "doc_init_runner" diff --git a/deployments/readme.md b/deployments/readme.md index ee1e6764..98d86f22 100644 --- a/deployments/readme.md +++ b/deployments/readme.md @@ -1,25 +1,26 @@ # Deployments ## Note about host service testing -If you want the docker prometheus in this stack to pull from your -locally running service on localhost:8080 then edit the -`compose.local.yaml` and change the reference from + +If you want the docker prometheus in this stack to pull from your +locally running service on localhost:8080 then edit the +`compose.local.yaml` and change the reference from `./prometheus.allmetrics.yaml:/etc/prometheus/prometheus.yml` to `./prometheus.localservice.yaml:/etc/prometheus/prometheus.yml` - ## Local -When running `task compose:up:local` prometheus will be available on -http://localhost:9090 + +When running `task compose:up:local` prometheus will be available on +`http://localhost:9090` When running `task compose:up` prometheus will be available on -http://localhost:9091 +`http://localhost:9091` To see which target services are being scraped by prometheus you can go to http:// localhost: [port] /targets - ### Local with service on host -If you need to run a service directly on the host for debugging then use + +If you need to run a service directly on the host for debugging then use `task compose:up:test` and then run the service like -`PGPORT=5430 go run ./cmd/queryService` \ No newline at end of file +`PGPORT=5430 go run ./cmd/queryAPI` diff --git a/devbox.json b/devbox.json index dc583b20..f2936269 100644 --- a/devbox.json +++ b/devbox.json @@ -40,13 +40,9 @@ "env_from": ".env", "packages": [ "golangci-lint@1.64.5", - "protolint@0.50.5", "yamllint@1.35.1", "sqlc@1.27.0", - "protoc-gen-go@1.35.1", - "protoc-gen-go-grpc@1.3.0", "go-migrate@4.18.1", - "protobuf@28.3", "go-task@3.39.2", "hadolint@2.12.0", "gotools@0.25.0", @@ -57,7 +53,9 @@ "postgresql@17.2", "bc@1.07.1", "gomarkdoc@1.1.0", - "go@1.24.0" + "go@1.24.0", + "sqlcheck@1.3", + "docker-client@27.3.1" ], "shell": { "init_hook": [ diff --git a/devbox.lock b/devbox.lock index 1a9c2f73..9e86e099 100644 --- a/devbox.lock +++ b/devbox.lock @@ -113,6 +113,54 @@ } } }, + "docker-client@27.3.1": { + "last_modified": "2024-12-03T12:40:06Z", + "resolved": "github:NixOS/nixpkgs/566e53c2ad750c84f6d31f9ccb9d00f823165550#docker-client", + "source": "devbox-search", + "version": "27.3.1", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/03vbya3x94lygm1242d7kqx63ia2qm4v-docker-27.3.1", + "default": true + } + ], + "store_path": "/nix/store/03vbya3x94lygm1242d7kqx63ia2qm4v-docker-27.3.1" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/7y6rl5mw8d4w95c05hdaxb36rzb4gxqr-docker-27.3.1", + "default": true + } + ], + "store_path": "/nix/store/7y6rl5mw8d4w95c05hdaxb36rzb4gxqr-docker-27.3.1" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/fn3prnmm4nnpw03z4lqilhqj9grdxvm7-docker-27.3.1", + "default": true + } + ], + "store_path": "/nix/store/fn3prnmm4nnpw03z4lqilhqj9grdxvm7-docker-27.3.1" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/n47072r68jh4x2avxwgxirj8652h2xdb-docker-27.3.1", + "default": true + } + ], + "store_path": "/nix/store/n47072r68jh4x2avxwgxirj8652h2xdb-docker-27.3.1" + } + } + }, "go-migrate@4.18.1": { "last_modified": "2024-12-23T21:10:33Z", "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#go-migrate", @@ -674,198 +722,6 @@ } } }, - "protobuf@28.3": { - "last_modified": "2024-12-03T12:40:06Z", - "resolved": "github:NixOS/nixpkgs/566e53c2ad750c84f6d31f9ccb9d00f823165550#protobuf", - "source": "devbox-search", - "version": "28.3", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/q04cfyxpr3ijb038bjwg6h10djlzrvzq-protobuf-28.3", - "default": true - } - ], - "store_path": "/nix/store/q04cfyxpr3ijb038bjwg6h10djlzrvzq-protobuf-28.3" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/ar3x733vglzmgwlwqm712chc4lsvmg6l-protobuf-28.3", - "default": true - } - ], - "store_path": "/nix/store/ar3x733vglzmgwlwqm712chc4lsvmg6l-protobuf-28.3" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/4xfgsh5dis62pr1776qnk6x6j5jn8zn0-protobuf-28.3", - "default": true - } - ], - "store_path": "/nix/store/4xfgsh5dis62pr1776qnk6x6j5jn8zn0-protobuf-28.3" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/q9masc42g6rwzkpi8ma4qwbnmkzj7vz2-protobuf-28.3", - "default": true - } - ], - "store_path": "/nix/store/q9masc42g6rwzkpi8ma4qwbnmkzj7vz2-protobuf-28.3" - } - } - }, - "protoc-gen-go-grpc@1.3.0": { - "last_modified": "2024-12-03T12:40:06Z", - "resolved": "github:NixOS/nixpkgs/566e53c2ad750c84f6d31f9ccb9d00f823165550#protoc-gen-go-grpc", - "source": "devbox-search", - "version": "1.3.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/lak8kwpnagiwham2byzg3qilr78bvqfv-protoc-gen-go-grpc-1.3.0", - "default": true - } - ], - "store_path": "/nix/store/lak8kwpnagiwham2byzg3qilr78bvqfv-protoc-gen-go-grpc-1.3.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/8chmakb7pix8kj4jv9gyyvdav2l22idk-protoc-gen-go-grpc-1.3.0", - "default": true - } - ], - "store_path": "/nix/store/8chmakb7pix8kj4jv9gyyvdav2l22idk-protoc-gen-go-grpc-1.3.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/7v7jj7d21im7saqy41vbrlwqjzzagnqp-protoc-gen-go-grpc-1.3.0", - "default": true - } - ], - "store_path": "/nix/store/7v7jj7d21im7saqy41vbrlwqjzzagnqp-protoc-gen-go-grpc-1.3.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/d79cxdsbdqs1l4aph985lflcix67bkb8-protoc-gen-go-grpc-1.3.0", - "default": true - } - ], - "store_path": "/nix/store/d79cxdsbdqs1l4aph985lflcix67bkb8-protoc-gen-go-grpc-1.3.0" - } - } - }, - "protoc-gen-go@1.35.1": { - "last_modified": "2024-11-16T04:25:12Z", - "resolved": "github:NixOS/nixpkgs/34a626458d686f1b58139620a8b2793e9e123bba#protoc-gen-go", - "source": "devbox-search", - "version": "1.35.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/5i406gv649fg1g7s8rcajbknm0kvsm85-protoc-gen-go-1.35.1", - "default": true - } - ], - "store_path": "/nix/store/5i406gv649fg1g7s8rcajbknm0kvsm85-protoc-gen-go-1.35.1" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/i42sm8xdgh3v1434q0haxqv0akxw2k60-protoc-gen-go-1.35.1", - "default": true - } - ], - "store_path": "/nix/store/i42sm8xdgh3v1434q0haxqv0akxw2k60-protoc-gen-go-1.35.1" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/34b5ry7cvnvckvgaf2xd4a46p78z1w2i-protoc-gen-go-1.35.1", - "default": true - } - ], - "store_path": "/nix/store/34b5ry7cvnvckvgaf2xd4a46p78z1w2i-protoc-gen-go-1.35.1" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/0l0x36ajfyr7gav993hw2i4g39zl9x08-protoc-gen-go-1.35.1", - "default": true - } - ], - "store_path": "/nix/store/0l0x36ajfyr7gav993hw2i4g39zl9x08-protoc-gen-go-1.35.1" - } - } - }, - "protolint@0.50.5": { - "last_modified": "2024-11-28T07:51:56Z", - "resolved": "github:NixOS/nixpkgs/226216574ada4c3ecefcbbec41f39ce4655f78ef#protolint", - "source": "devbox-search", - "version": "0.50.5", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/039zwhkiv8klph9nk2yicyrddh3d0xxh-protolint-0.50.5", - "default": true - } - ], - "store_path": "/nix/store/039zwhkiv8klph9nk2yicyrddh3d0xxh-protolint-0.50.5" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/rhmmdymbshdw6f8s9v00x1xh4kl4dv94-protolint-0.50.5", - "default": true - } - ], - "store_path": "/nix/store/rhmmdymbshdw6f8s9v00x1xh4kl4dv94-protolint-0.50.5" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/kinv97rh0zsa45mnhnll9qnd4i0r13a0-protolint-0.50.5", - "default": true - } - ], - "store_path": "/nix/store/kinv97rh0zsa45mnhnll9qnd4i0r13a0-protolint-0.50.5" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/1qz26rz830l9zf2dlg27mvgk9g53jdxm-protolint-0.50.5", - "default": true - } - ], - "store_path": "/nix/store/1qz26rz830l9zf2dlg27mvgk9g53jdxm-protolint-0.50.5" - } - } - }, "sqlc@1.27.0": { "last_modified": "2024-12-23T21:10:33Z", "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#sqlc", @@ -914,6 +770,54 @@ } } }, + "sqlcheck@1.3": { + "last_modified": "2025-02-07T11:26:36Z", + "resolved": "github:NixOS/nixpkgs/d98abf5cf5914e5e4e9d57205e3af55ca90ffc1d#sqlcheck", + "source": "devbox-search", + "version": "1.3", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/srp4f0d3hlf35sn9bjx48hxsg8a335qk-sqlcheck-1.3", + "default": true + } + ], + "store_path": "/nix/store/srp4f0d3hlf35sn9bjx48hxsg8a335qk-sqlcheck-1.3" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/548sicnzac0ckzgjhs3kh7fybmxpk81s-sqlcheck-1.3", + "default": true + } + ], + "store_path": "/nix/store/548sicnzac0ckzgjhs3kh7fybmxpk81s-sqlcheck-1.3" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/77f59r1383ypf5byjfmfz93sskkfm0c9-sqlcheck-1.3", + "default": true + } + ], + "store_path": "/nix/store/77f59r1383ypf5byjfmfz93sskkfm0c9-sqlcheck-1.3" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/wi6hk3ff34y85bgjb5di7giz7i9lwdw6-sqlcheck-1.3", + "default": true + } + ], + "store_path": "/nix/store/wi6hk3ff34y85bgjb5di7giz7i9lwdw6-sqlcheck-1.3" + } + } + }, "vacuum-go@0.14.1": { "last_modified": "2024-11-28T07:51:56Z", "resolved": "github:NixOS/nixpkgs/226216574ada4c3ecefcbbec41f39ce4655f78ef#vacuum-go", diff --git a/docs/README.md b/docs/README.md index 6fc81f17..4072f0a8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -74,17 +74,7 @@ It demonstrates: 5. Proper error handling -## queryRunner - -**Listens For**: Body Containing Document ID and Query ID - -**Action**. - -Run the query for the given document and store the result. - -Events with the document id and downstream query ids are pushed to the QUERY queue. - -## queryService +## queryAPI This API currently manages all user entities to be managed. This allows users of the service to change required entities and processes. @@ -100,6 +90,16 @@ The entities in question: - Export - An export is a manually started process which outputs the results for a client to a given location. +## queryRunner + +**Listens For**: Body Containing Document ID and Query ID + +**Action**. + +Run the query for the given document and store the result. + +Events with the document id and downstream query ids are pushed to the QUERY queue. + ## querySyncRunner **Listens For**: Body Containing Document ID diff --git a/go.mod b/go.mod index af83c9c5..5b6cbd1b 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/labstack/echo-contrib v0.17.2 github.com/labstack/echo/v4 v4.13.3 github.com/lib/pq v1.10.9 + github.com/oapi-codegen/echo-middleware v1.0.2 github.com/oapi-codegen/runtime v1.1.1 github.com/pdfcpu/pdfcpu v0.9.1 github.com/prometheus/client_golang v1.21.1 @@ -48,6 +49,7 @@ require ( github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect diff --git a/go.sum b/go.sum index c5b7c6df..fac919be 100644 --- a/go.sum +++ b/go.sum @@ -135,6 +135,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 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/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -224,6 +226,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/oapi-codegen/echo-middleware v1.0.2 h1:oNBqiE7jd/9bfGNk/bpbX2nqWrtPc+LL4Boya8Wl81U= +github.com/oapi-codegen/echo-middleware v1.0.2/go.mod h1:5J6MFcGqrpWLXpbKGZtRPZViLIHyyyUHlkqg6dT2R4E= github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/oasdiff/yaml v0.0.0-20241214135536-5f7845c759c8 h1:9djga8U4+/TQzv5iMlZHZ/qbGQB9V2nlnk2bmiG+uBs= diff --git a/internal/client/create_test.go b/internal/client/create_test.go index 003f36b9..55ae7de2 100644 --- a/internal/client/create_test.go +++ b/internal/client/create_test.go @@ -38,7 +38,7 @@ func TestCreate(t *testing.T) { ) id, err := svc.Create(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, aid, id) } @@ -54,7 +54,7 @@ func TestNormalizeCreate(t *testing.T) { } err := svc.normalizeCreate(params) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "client_name", params.Name) assert.Equal(t, "external_id", params.ExternalId) }) @@ -65,7 +65,7 @@ func TestNormalizeCreate(t *testing.T) { } err := svc.normalizeCreate(params) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "client_name", params.Name) assert.Equal(t, "external_id", params.ExternalId) }) diff --git a/internal/client/get_test.go b/internal/client/get_test.go index 60c68169..e9067845 100644 --- a/internal/client/get_test.go +++ b/internal/client/get_test.go @@ -35,7 +35,7 @@ func TestGet(t *testing.T) { ) cli, err := svc.Get(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &Client{ ID: id, ExternalID: "client_id", @@ -72,7 +72,7 @@ func TestGetByExternalId(t *testing.T) { ) cli, err := svc.GetByExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &Client{ ID: id, ExternalID: "client_id", diff --git a/internal/client/serviceprivate_test.go b/internal/client/serviceprivate_test.go index 000b962a..da567e06 100644 --- a/internal/client/serviceprivate_test.go +++ b/internal/client/serviceprivate_test.go @@ -5,6 +5,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNormalizeName(t *testing.T) { @@ -24,7 +25,7 @@ func TestNormalizeName(t *testing.T) { } for key, value := range names { err := normalizeName(&key) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, value, key) } @@ -62,19 +63,19 @@ func TestNormalizeNameUpdate(t *testing.T) { } err := c.normalizeNameUpdate(nil) - assert.NoError(t, err) + require.NoError(t, err) v := "update_name" val := &v err = c.normalizeNameUpdate(&val) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, val) assert.Equal(t, "update_name", *val) v = c.Name val = &v err = c.normalizeNameUpdate(&val) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, val) v = "###" diff --git a/internal/client/status_test.go b/internal/client/status_test.go index 5bcccc93..0a2f0a11 100644 --- a/internal/client/status_test.go +++ b/internal/client/status_test.go @@ -41,7 +41,7 @@ func TestGetStatusByExternalId(t *testing.T) { ) issynced, err := svc.GetStatusByExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, client.IN_SYNC, issynced) }) t.Run("not synced", func(t *testing.T) { @@ -55,7 +55,7 @@ func TestGetStatusByExternalId(t *testing.T) { ) issynced, err := svc.GetStatusByExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, client.NOT_SYNCED, issynced) }) t.Run("not syncing", func(t *testing.T) { @@ -65,7 +65,7 @@ func TestGetStatusByExternalId(t *testing.T) { ) issynced, err := svc.GetStatusByExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, client.NOT_SYNCING, issynced) }) t.Run("db error", func(t *testing.T) { diff --git a/internal/client/sync/sync_test.go b/internal/client/sync/sync_test.go index c1c3a7fa..13c05a8e 100644 --- a/internal/client/sync/sync_test.go +++ b/internal/client/sync/sync_test.go @@ -15,7 +15,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/google/uuid" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) @@ -42,7 +41,7 @@ func TestTrigger(t *testing.T) { svc := New(cfg) clientId := uuid.New() - docs := []document.Document{ + docs := []document.DocumentSummary{ { ID: uuid.New(), ClientID: clientId, @@ -85,7 +84,7 @@ func TestTrigger(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.Sync(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("empty batch", func(t *testing.T) { ctx := context.Background() @@ -111,6 +110,6 @@ func TestTrigger(t *testing.T) { ) err = svc.Sync(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) }) } diff --git a/internal/client/update_test.go b/internal/client/update_test.go index 0e513d56..c134037b 100644 --- a/internal/client/update_test.go +++ b/internal/client/update_test.go @@ -90,7 +90,7 @@ func TestNormalizeUpdateParams(t *testing.T) { CanSync: &cs, } err = svc.normalizeUpdateParams(current.ID, current, update) - assert.NoError(t, err) + require.NoError(t, err) n = "updated_client" cs = true assert.EqualExportedValues(t, Update{ @@ -128,7 +128,7 @@ func TestSubmitUpdate(t *testing.T) { pool.ExpectCommit() err = svc.submitUpdate(ctx, c.ID, &update) - assert.NoError(t, err) + require.NoError(t, err) c.CanSync = true update.CanSync = &c.CanSync @@ -139,7 +139,7 @@ func TestSubmitUpdate(t *testing.T) { pool.ExpectCommit() err = svc.submitUpdate(ctx, c.ID, &update) - assert.NoError(t, err) + require.NoError(t, err) c.Name = "updated_name" update.Name = &c.Name @@ -151,7 +151,7 @@ func TestSubmitUpdate(t *testing.T) { pool.ExpectCommit() err = svc.submitUpdate(ctx, c.ID, &update) - assert.NoError(t, err) + require.NoError(t, err) } func TestUpdateByExternalId(t *testing.T) { diff --git a/internal/collector/get_test.go b/internal/collector/get_test.go index 8ef00690..4152e7ad 100644 --- a/internal/collector/get_test.go +++ b/internal/collector/get_test.go @@ -46,7 +46,7 @@ func TestGetByClientID(t *testing.T) { ) coll, err := svc.GetByClientID(ctx, ogc.ClientID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, ogc, *coll) } @@ -77,6 +77,6 @@ func TestListQueries(t *testing.T) { ) qs, err := svc.ListQueries(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, ogc, qs) } diff --git a/internal/collector/parse_test.go b/internal/collector/parse_test.go index df75c03a..3a81d7b7 100644 --- a/internal/collector/parse_test.go +++ b/internal/collector/parse_test.go @@ -9,11 +9,12 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseDBCollector(t *testing.T) { c, err := parseDBCollector(nil) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, c) minCleanV := int64(1) @@ -32,7 +33,7 @@ func TestParseDBCollector(t *testing.T) { Mintextversion: ogc.MinTextVersion, Fields: []byte(fmt.Sprintf("{\"example_key\":\"%s\"}", ogc.Fields["example_key"])), }) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, ogc, *c) ogc.MinCleanVersion = 0 @@ -41,6 +42,6 @@ func TestParseDBCollector(t *testing.T) { Clientid: database.MustToDBUUID(ogc.ClientID), Fields: []byte(fmt.Sprintf("{\"example_key\":\"%s\"}", ogc.Fields["example_key"])), }) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, ogc, *c) } diff --git a/internal/collector/set/set_test.go b/internal/collector/set/set_test.go index 4aa0c8b7..74e695ce 100644 --- a/internal/collector/set/set_test.go +++ b/internal/collector/set/set_test.go @@ -17,7 +17,6 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) @@ -84,7 +83,7 @@ func TestSet(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.SetByClientId(ctx, current.ClientID, &update) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("no collector", func(t *testing.T) { current := collector.Collector{ @@ -125,7 +124,7 @@ func TestSet(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.SetByClientId(ctx, current.ClientID, &update) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -192,7 +191,7 @@ func TestSetByExternalId(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.SetByClientExternalId(ctx, externalId, &update) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("no collector", func(t *testing.T) { current := collector.Collector{ @@ -237,6 +236,6 @@ func TestSetByExternalId(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.SetByClientExternalId(ctx, externalId, &update) - assert.NoError(t, err) + require.NoError(t, err) }) } diff --git a/internal/collector/set/setprivate_test.go b/internal/collector/set/setprivate_test.go index 057e2efc..f9c670b7 100644 --- a/internal/collector/set/setprivate_test.go +++ b/internal/collector/set/setprivate_test.go @@ -68,7 +68,7 @@ func TestGetSetParams(t *testing.T) { clientId := uuid.New() dbparams, err := svc.getSetParams(ctx, clientId, ¤t, ¶ms) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &dbSetParams{ ClientID: database.MustToDBUUID(clientId), ActiveVersion: &aV, @@ -227,7 +227,7 @@ func TestSubmitSet(t *testing.T) { pool.ExpectCommit() err = svc.submitSet(ctx, ¤t, ¶ms) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("only active version", func(t *testing.T) { @@ -264,7 +264,7 @@ func TestSubmitSet(t *testing.T) { pool.ExpectCommit() err = svc.submitSet(ctx, ¤t, ¶ms) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -283,7 +283,7 @@ func TestNormalizeActiveVersion(t *testing.T) { } err := svc.normalizeActiveVersion(¤t, nil) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("no update", func(t *testing.T) { @@ -293,7 +293,7 @@ func TestNormalizeActiveVersion(t *testing.T) { } update := SetParams{} err := svc.normalizeActiveVersion(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.ActiveVersion) }) @@ -307,7 +307,7 @@ func TestNormalizeActiveVersion(t *testing.T) { ActiveVersion: &version, } err := svc.normalizeActiveVersion(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.ActiveVersion) }) @@ -321,7 +321,7 @@ func TestNormalizeActiveVersion(t *testing.T) { ActiveVersion: &version, } err := svc.normalizeActiveVersion(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, version, *update.ActiveVersion) }) @@ -350,7 +350,7 @@ func TestNormalizeCodeVersions(t *testing.T) { t.Run("nil update", func(t *testing.T) { current := collector.Collector{} err := svc.normalizeCodeVersions(¤t, nil) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("empty", func(t *testing.T) { @@ -358,7 +358,7 @@ func TestNormalizeCodeVersions(t *testing.T) { update := SetParams{} err := svc.normalizeCodeVersions(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.MinCleanVersion) assert.Nil(t, update.MinTextVersion) }) @@ -370,7 +370,7 @@ func TestNormalizeCodeVersions(t *testing.T) { cv := int64(1) update.MinCleanVersion = &cv err := svc.normalizeCodeVersions(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, cv, *update.MinCleanVersion) assert.Nil(t, update.MinTextVersion) }) @@ -382,7 +382,7 @@ func TestNormalizeCodeVersions(t *testing.T) { tv := int64(1) update.MinTextVersion = &tv err := svc.normalizeCodeVersions(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.MinCleanVersion) assert.Equal(t, tv, *update.MinTextVersion) }) @@ -394,7 +394,7 @@ func TestNormalizeCodeVersions(t *testing.T) { current.MinCleanVersion = 1 current.MinTextVersion = 1 err := svc.normalizeCodeVersions(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.MinCleanVersion) assert.Nil(t, update.MinTextVersion) }) @@ -407,7 +407,7 @@ func TestNormalizeCodeVersions(t *testing.T) { update.MinCleanVersion = ¤t.MinCleanVersion err := svc.normalizeCodeVersions(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.MinCleanVersion) assert.Nil(t, update.MinTextVersion) }) @@ -420,7 +420,7 @@ func TestNormalizeCodeVersions(t *testing.T) { update.MinTextVersion = ¤t.MinTextVersion err := svc.normalizeCodeVersions(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.MinCleanVersion) assert.Nil(t, update.MinTextVersion) }) @@ -435,7 +435,7 @@ func TestNormalizeCodeVersions(t *testing.T) { update.MinCleanVersion = ¤t.MinCleanVersion update.MinTextVersion = ¤t.MinTextVersion err := svc.normalizeCodeVersions(¤t, &update) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, update.MinCleanVersion) assert.Nil(t, update.MinTextVersion) }) @@ -545,7 +545,7 @@ func TestNormalizeSetFieldsToDB(t *testing.T) { ) dbparams, err := svc.normalizeSetFieldsToDB(ctx, current, &fields) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &map[string]pgtype.UUID{ "example_key": database.MustToDBUUID(fields["example_key"]), }, dbparams) @@ -598,7 +598,7 @@ func TestNormalizeSetFieldsToDB(t *testing.T) { } val, err := svc.normalizeSetFieldsToDB(ctx, current, &fields) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, val) }) } @@ -635,7 +635,7 @@ func TestInformSet(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.informSet(ctx, &update) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("with no update", func(t *testing.T) { ctx := context.Background() @@ -656,7 +656,7 @@ func TestInformSet(t *testing.T) { } err = svc.informSet(ctx, &update) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -684,7 +684,7 @@ func TestNormalizeFieldsToDB(t *testing.T) { ) dbparams, err := svc.normalizeFieldsToDB(ctx, &fields) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &map[string]pgtype.UUID{ "example_key": database.MustToDBUUID(fields["example_key"]), }, dbparams) diff --git a/internal/database/migrations/migrations_test.go b/internal/database/migrations/migrations_test.go index 3eb400b2..2ab81bae 100644 --- a/internal/database/migrations/migrations_test.go +++ b/internal/database/migrations/migrations_test.go @@ -12,6 +12,7 @@ import ( "queryorchestration/internal/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestRunMigrations(t *testing.T) { @@ -30,7 +31,7 @@ func TestRunMigrations(t *testing.T) { defer cleanup() err := migrations.Run(ctx, cfg) - assert.NoError(t, err) + require.NoError(t, err) } func TestRunMigrationsNoDB(t *testing.T) { diff --git a/internal/database/parseuuid_test.go b/internal/database/parseuuid_test.go index 29cad124..e18d42a6 100644 --- a/internal/database/parseuuid_test.go +++ b/internal/database/parseuuid_test.go @@ -8,13 +8,14 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestToDBUUID(t *testing.T) { id := uuid.New() dbID, err := database.ToDBUUID(id) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, dbID.Valid) assert.Equal(t, id.String(), uuid.UUID(dbID.Bytes).String()) @@ -24,7 +25,7 @@ func TestToDBUUIDNil(t *testing.T) { id := uuid.Nil dbID, err := database.ToDBUUID(id) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, dbID.Valid) assert.Equal(t, id.String(), uuid.UUID(dbID.Bytes).String()) @@ -34,7 +35,7 @@ func TestToDBUUIDArray(t *testing.T) { ids := []uuid.UUID{uuid.Nil, uuid.New()} dbIDs, err := database.ToDBUUIDArray(ids) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, dbIDs, 1) assert.ElementsMatch(t, []pgtype.UUID{database.MustToDBUUID(ids[1])}, dbIDs) @@ -42,10 +43,10 @@ func TestToDBUUIDArray(t *testing.T) { func TestToUUID(t *testing.T) { dbID, err := database.ToDBUUID(uuid.New()) - assert.NoError(t, err) + require.NoError(t, err) id, err := database.ToUUID(dbID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id.String(), uuid.UUID(dbID.Bytes).String()) } @@ -55,7 +56,7 @@ func TestToUUIDArray(t *testing.T) { dbIDs := database.MustToDBUUIDArray(ogIDs) ids, err := database.ToUUIDArray(dbIDs) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, ids, 1) assert.ElementsMatch(t, []uuid.UUID{ogIDs[1]}, ids) diff --git a/internal/database/repository/clean_test.go b/internal/database/repository/clean_test.go index 19686581..9d0cc655 100644 --- a/internal/database/repository/clean_test.go +++ b/internal/database/repository/clean_test.go @@ -11,6 +11,7 @@ import ( "queryorchestration/internal/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestClean(t *testing.T) { @@ -34,18 +35,18 @@ func TestClean(t *testing.T) { Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) hash := "example_hash" id, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: hash, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, id) isclean, err := queries.HasDocumentCleanEntry(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, isclean) bucket := "example_bucket" @@ -71,19 +72,19 @@ func TestClean(t *testing.T) { Documentid: id, Fail: fail, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Version: 1, Cleanid: failcleanid, }) - assert.NoError(t, err) + require.NoError(t, err) isclean, err = queries.HasDocumentCleanEntry(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, isclean) clean, err := queries.GetCleanEntry(ctx, failcleanid) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, clean.Documentid) assert.Nil(t, clean.Bucket) assert.Nil(t, clean.Key) @@ -97,19 +98,19 @@ func TestClean(t *testing.T) { Key: &key, Mimetype: mimetype, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Version: 2, Cleanid: cleanid, }) - assert.NoError(t, err) + require.NoError(t, err) isclean, err = queries.HasDocumentCleanEntry(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, isclean) clean, err = queries.GetCleanEntry(ctx, cleanid) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, clean.Documentid) assert.False(t, clean.Fail.Valid) assert.Equal(t, bucket, *clean.Bucket) @@ -119,11 +120,11 @@ func TestClean(t *testing.T) { assert.Equal(t, cleanid, clean.ID) docclean, err := queries.GetCleanEntryByDocId(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, clean, docclean) recent, err := queries.GetMostRecentDocumentCleanEntry(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, clean.Documentid, recent.Documentid) assert.Equal(t, clean.Bucket, recent.Bucket) assert.Equal(t, clean.Key, recent.Key) @@ -133,25 +134,25 @@ func TestClean(t *testing.T) { assert.Equal(t, clean.ID, recent.ID) version, err := queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Clientid: clientId, Versionid: version, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetCollectorCleanVersion(ctx, &repository.SetCollectorCleanVersionParams{ Clientid: clientId, Versionid: 5, Addedversion: version, }) - assert.NoError(t, err) + require.NoError(t, err) isclean, err = queries.HasDocumentCleanEntry(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, isclean) recent, err = queries.GetMostRecentDocumentCleanEntry(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, clean.Documentid, recent.Documentid) assert.Equal(t, clean.Bucket, recent.Bucket) assert.Equal(t, clean.Key, recent.Key) diff --git a/internal/database/repository/client.sql.go b/internal/database/repository/client.sql.go index 51bb3afa..842969e8 100644 --- a/internal/database/repository/client.sql.go +++ b/internal/database/repository/client.sql.go @@ -96,17 +96,19 @@ doc_clean_entries as ( SELECT d.id AS document_id, d.clientId as client_id, - cte.id AS clean_entry_id + cte.id AS clean_entry_id, + cte.fail as clean_fail FROM docs d LEFT JOIN currentCleanEntries cte ON cte.documentId = d.id - WHERE cte.id is null or cte.id is not null and cte.fail is null ), doc_text_entries AS ( -- Documents with their current text entries SELECT d.document_id, - cte.id AS text_entry_id + cte.id AS text_entry_id, + d.clean_entry_id, + d.clean_fail FROM doc_clean_entries d LEFT JOIN currentTextEntries cte ON cte.cleanEntryId = d.clean_entry_id @@ -123,6 +125,7 @@ required_results AS ( JOIN collectorQueryDependencyTree cqdt ON cqdt.clientId = d.client_id JOIN doc_text_entries dte ON dte.document_id = d.document_id and dte.text_entry_id IS NOT NULL + where d.clean_fail is null ), existing_results AS ( -- Valid results that exist @@ -159,17 +162,23 @@ SELECT ( OR -- Documents with no text entries - (NOT EXISTS (SELECT 1 FROM doc_text_entries WHERE text_entry_id IS NULL) + ( + NOT EXISTS ( + SELECT 1 FROM doc_text_entries + where clean_entry_id is null or + (clean_fail is null and text_entry_id is null) + ) - and + and - -- Documents with missing results - NOT EXISTS (SELECT 1 FROM missing_results) + -- Documents with missing results + NOT EXISTS (SELECT 1 FROM missing_results) - and + and - -- Documents with missing dependencies - NOT EXISTS (SELECT 1 FROM dependency_check)) + -- Documents with missing dependencies + NOT EXISTS (SELECT 1 FROM dependency_check) + )::bool )::bool as is_synced ` @@ -185,17 +194,19 @@ SELECT ( // SELECT // d.id AS document_id, // d.clientId as client_id, -// cte.id AS clean_entry_id +// cte.id AS clean_entry_id, +// cte.fail as clean_fail // FROM // docs d // LEFT JOIN currentCleanEntries cte ON cte.documentId = d.id -// WHERE cte.id is null or cte.id is not null and cte.fail is null // ), // doc_text_entries AS ( // -- Documents with their current text entries // SELECT // d.document_id, -// cte.id AS text_entry_id +// cte.id AS text_entry_id, +// d.clean_entry_id, +// d.clean_fail // FROM // doc_clean_entries d // LEFT JOIN currentTextEntries cte ON cte.cleanEntryId = d.clean_entry_id @@ -212,6 +223,7 @@ SELECT ( // JOIN collectorQueryDependencyTree cqdt ON cqdt.clientId = d.client_id // JOIN doc_text_entries dte ON dte.document_id = d.document_id // and dte.text_entry_id IS NOT NULL +// where d.clean_fail is null // ), // existing_results AS ( // -- Valid results that exist @@ -248,17 +260,23 @@ SELECT ( // OR // // -- Documents with no text entries -// (NOT EXISTS (SELECT 1 FROM doc_text_entries WHERE text_entry_id IS NULL) +// ( +// NOT EXISTS ( +// SELECT 1 FROM doc_text_entries +// where clean_entry_id is null or +// (clean_fail is null and text_entry_id is null) +// ) // -// and +// and // -// -- Documents with missing results -// NOT EXISTS (SELECT 1 FROM missing_results) +// -- Documents with missing results +// NOT EXISTS (SELECT 1 FROM missing_results) // -// and +// and // -// -- Documents with missing dependencies -// NOT EXISTS (SELECT 1 FROM dependency_check)) +// -- Documents with missing dependencies +// NOT EXISTS (SELECT 1 FROM dependency_check) +// )::bool // )::bool as is_synced func (q *Queries) IsClientSynced(ctx context.Context, dollar_1 pgtype.UUID) (bool, error) { row := q.db.QueryRow(ctx, isClientSynced, dollar_1) diff --git a/internal/database/repository/client_test.go b/internal/database/repository/client_test.go index 7761bb80..471469b0 100644 --- a/internal/database/repository/client_test.go +++ b/internal/database/repository/client_test.go @@ -11,6 +11,7 @@ import ( "queryorchestration/internal/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestClient(t *testing.T) { @@ -36,11 +37,11 @@ func TestClient(t *testing.T) { Name: name, Externalid: externalId, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, id) client, err := queries.GetClient(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullclient{ ID: id, Name: name, @@ -49,7 +50,7 @@ func TestClient(t *testing.T) { }, client) externalClient, err := queries.GetClientByExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, client, externalClient) name = "updated_client" @@ -57,10 +58,10 @@ func TestClient(t *testing.T) { ID: id, Name: name, }) - assert.NoError(t, err) + require.NoError(t, err) client, err = queries.GetClient(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullclient{ ID: id, Name: name, @@ -72,10 +73,10 @@ func TestClient(t *testing.T) { Clientid: id, Cansync: true, }) - assert.NoError(t, err) + require.NoError(t, err) client, err = queries.GetClient(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullclient{ ID: id, Name: name, @@ -102,5 +103,5 @@ func TestClient(t *testing.T) { Name: "sameid", Externalid: "sameid", }) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/database/repository/collector_test.go b/internal/database/repository/collector_test.go index 767a525b..75756fe2 100644 --- a/internal/database/repository/collector_test.go +++ b/internal/database/repository/collector_test.go @@ -14,6 +14,7 @@ import ( "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCollector(t *testing.T) { @@ -34,34 +35,34 @@ func TestCollector(t *testing.T) { queries := cfg.GetDBQueries() contextId, err := queries.CreateQuery(ctx, repository.QuerytypeContextFull) - assert.NoError(t, err) + require.NoError(t, err) jsonId, err := queries.CreateQuery(ctx, repository.QuerytypeJsonExtractor) - assert.NoError(t, err) + require.NoError(t, err) version, err := queries.AddLatestQueryVersion(ctx, jsonId) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: jsonId, Versionid: version, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int32(1), version) err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ Queryid: jsonId, Requiredqueryid: contextId, Addedversion: version, }) - assert.NoError(t, err) + require.NoError(t, err) clientId, err := queries.CreateClient(ctx, &repository.CreateClientParams{ Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) minCleanVersion := int64(2) minTextVersion := int64(4) coll, err := queries.GetCollectorByClientID(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivecollector{ Clientid: clientId, Mincleanversion: 0, @@ -71,11 +72,11 @@ func TestCollector(t *testing.T) { }, coll) version, err = queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int32(1), version) coll, err = queries.GetCollectorByClientID(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivecollector{ Clientid: clientId, Mincleanversion: 0, @@ -88,10 +89,10 @@ func TestCollector(t *testing.T) { Versionid: 1, Clientid: clientId, }) - assert.NoError(t, err) + require.NoError(t, err) coll, err = queries.GetCollectorByClientID(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivecollector{ Clientid: clientId, Mincleanversion: 0, @@ -106,17 +107,17 @@ func TestCollector(t *testing.T) { Addedversion: 1, Name: "example_key", }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetCollectorTextVersion(ctx, &repository.SetCollectorTextVersionParams{ Clientid: clientId, Addedversion: 1, Versionid: minTextVersion, }) - assert.NoError(t, err) + require.NoError(t, err) coll, err = queries.GetCollectorByClientID(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivecollector{ Clientid: clientId, Mincleanversion: 0, @@ -131,10 +132,10 @@ func TestCollector(t *testing.T) { Addedversion: 1, Versionid: minCleanVersion, }) - assert.NoError(t, err) + require.NoError(t, err) coll, err = queries.GetCollectorByClientID(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivecollector{ Clientid: clientId, Mincleanversion: minCleanVersion, @@ -145,7 +146,7 @@ func TestCollector(t *testing.T) { }, coll) qs, err := queries.ListCollectorQueries(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 2) assert.ElementsMatch(t, []*repository.Collectorquerydependencytree{ { @@ -165,7 +166,7 @@ func TestCollector(t *testing.T) { }, qs) version, err = queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int32(2), version) err = queries.RemoveCollectorQuery(ctx, &repository.RemoveCollectorQueryParams{ @@ -173,23 +174,23 @@ func TestCollector(t *testing.T) { Queryid: jsonId, Removedversion: &version, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Versionid: 2, Clientid: clientId, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetCollectorTextVersion(ctx, &repository.SetCollectorTextVersionParams{ Clientid: clientId, Versionid: minTextVersion + 1, Addedversion: version, }) - assert.NoError(t, err) + require.NoError(t, err) coll, err = queries.GetCollectorByClientID(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivecollector{ Clientid: clientId, Mincleanversion: minCleanVersion, @@ -204,10 +205,10 @@ func TestCollector(t *testing.T) { Versionid: minCleanVersion + 1, Addedversion: version, }) - assert.NoError(t, err) + require.NoError(t, err) coll, err = queries.GetCollectorByClientID(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivecollector{ Clientid: clientId, Mincleanversion: minCleanVersion + 1, diff --git a/internal/database/repository/db_test.go b/internal/database/repository/db_test.go index cb4ab603..1336ae8b 100644 --- a/internal/database/repository/db_test.go +++ b/internal/database/repository/db_test.go @@ -32,7 +32,7 @@ func TestQueriesWithTx(t *testing.T) { pool.ExpectBeginTx(pgx.TxOptions{}) tx, err := pool.Begin(ctx) - assert.NoError(t, err) + require.NoError(t, err) txQueries := queries.WithTx(tx) assert.NotNil(t, txQueries) diff --git a/internal/database/repository/document.sql.go b/internal/database/repository/document.sql.go index 3117c232..0e77edbe 100644 --- a/internal/database/repository/document.sql.go +++ b/internal/database/repository/document.sql.go @@ -48,20 +48,6 @@ func (q *Queries) CreateDocument(ctx context.Context, arg *CreateDocumentParams) return id, err } -const getDocument = `-- name: GetDocument :one -SELECT id, clientId, hash FROM documents WHERE id = $1 LIMIT 1 -` - -// GetDocument -// -// SELECT id, clientId, hash FROM documents WHERE id = $1 LIMIT 1 -func (q *Queries) GetDocument(ctx context.Context, id pgtype.UUID) (*Document, error) { - row := q.db.QueryRow(ctx, getDocument, id) - var i Document - err := row.Scan(&i.ID, &i.Clientid, &i.Hash) - return &i, err -} - const getDocumentEntry = `-- name: GetDocumentEntry :one SELECT documentId, bucket, key FROM documentEntries WHERE documentId = $1 ORDER BY id DESC LIMIT 1 ` @@ -82,6 +68,80 @@ func (q *Queries) GetDocumentEntry(ctx context.Context, documentid pgtype.UUID) return &i, err } +const getDocumentExternal = `-- name: GetDocumentExternal :one +WITH +docs AS ( + SELECT id, hash, clientId + FROM documents + WHERE id = $1 +), +namedResults AS ( + SELECT + q.name, + dd.id, + d.value + FROM currentCollectorQueries AS q + JOIN docs as dd on dd.clientId = q.clientId + LEFT JOIN listValidDocumentResults($1) AS d + ON d.queryId = q.queryId and q.name is not null +) +SELECT + d.id, + c.externalId AS clientId, + d.hash, + COALESCE(jsonb_object_agg(r.name, r.value) FILTER (WHERE r.name IS NOT NULL), '{}') AS fields +FROM docs AS d +JOIN clients AS c ON c.id = d.clientId +LEFT JOIN namedResults AS r ON d.id = r.id +GROUP BY d.id, c.externalId, d.hash +` + +type GetDocumentExternalRow struct { + ID pgtype.UUID `db:"id"` + Clientid string `db:"clientid"` + Hash string `db:"hash"` + Fields []byte `db:"fields"` +} + +// GetDocumentExternal +// +// WITH +// docs AS ( +// SELECT id, hash, clientId +// FROM documents +// WHERE id = $1 +// ), +// namedResults AS ( +// SELECT +// q.name, +// dd.id, +// d.value +// FROM currentCollectorQueries AS q +// JOIN docs as dd on dd.clientId = q.clientId +// LEFT JOIN listValidDocumentResults($1) AS d +// ON d.queryId = q.queryId and q.name is not null +// ) +// SELECT +// d.id, +// c.externalId AS clientId, +// d.hash, +// COALESCE(jsonb_object_agg(r.name, r.value) FILTER (WHERE r.name IS NOT NULL), '{}') AS fields +// FROM docs AS d +// JOIN clients AS c ON c.id = d.clientId +// LEFT JOIN namedResults AS r ON d.id = r.id +// GROUP BY d.id, c.externalId, d.hash +func (q *Queries) GetDocumentExternal(ctx context.Context, documentid pgtype.UUID) (*GetDocumentExternalRow, error) { + row := q.db.QueryRow(ctx, getDocumentExternal, documentid) + var i GetDocumentExternalRow + err := row.Scan( + &i.ID, + &i.Clientid, + &i.Hash, + &i.Fields, + ) + return &i, err +} + const getDocumentIDByHash = `-- name: GetDocumentIDByHash :one SELECT id FROM documents WHERE hash = $1 and clientId = $2 ` @@ -101,6 +161,20 @@ func (q *Queries) GetDocumentIDByHash(ctx context.Context, arg *GetDocumentIDByH return id, err } +const getDocumentSummary = `-- name: GetDocumentSummary :one +SELECT id, clientId, hash FROM documents WHERE id = $1 +` + +// GetDocumentSummary +// +// SELECT id, clientId, hash FROM documents WHERE id = $1 +func (q *Queries) GetDocumentSummary(ctx context.Context, id pgtype.UUID) (*Document, error) { + row := q.db.QueryRow(ctx, getDocumentSummary, id) + var i Document + err := row.Scan(&i.ID, &i.Clientid, &i.Hash) + return &i, err +} + const listDocumentIDsBatch = `-- name: ListDocumentIDsBatch :many SELECT id, totalCount FROM listDocumentIDs($1, $2, $3) ` @@ -142,50 +216,25 @@ func (q *Queries) ListDocumentIDsBatch(ctx context.Context, arg *ListDocumentIDs const listDocumentsByClientExternalId = `-- name: ListDocumentsByClientExternalId :many WITH client as ( SELECT id from clients where externalId = $1 -), -docs as ( - SELECT d.id - from documents as d - JOIN client as c on d.clientId = c.id -), -entries as ( - SELECT - de.documentId, - de.bucket, - de.key, - ROW_NUMBER() OVER (PARTITION BY de.documentId ORDER BY de.id DESC) as rowNumber - FROM docs d - JOIN documentEntries de on d.id = de.documentId ) -SELECT documentId as id, bucket, key from entries WHERE rowNumber = 1 +SELECT d.id, d.hash + from documents as d + JOIN client as c on d.clientId = c.id ` type ListDocumentsByClientExternalIdRow struct { - ID pgtype.UUID `db:"id"` - Bucket string `db:"bucket"` - Key string `db:"key"` + ID pgtype.UUID `db:"id"` + Hash string `db:"hash"` } // ListDocumentsByClientExternalId // // WITH client as ( // SELECT id from clients where externalId = $1 -// ), -// docs as ( -// SELECT d.id -// from documents as d -// JOIN client as c on d.clientId = c.id -// ), -// entries as ( -// SELECT -// de.documentId, -// de.bucket, -// de.key, -// ROW_NUMBER() OVER (PARTITION BY de.documentId ORDER BY de.id DESC) as rowNumber -// FROM docs d -// JOIN documentEntries de on d.id = de.documentId // ) -// SELECT documentId as id, bucket, key from entries WHERE rowNumber = 1 +// SELECT d.id, d.hash +// from documents as d +// JOIN client as c on d.clientId = c.id func (q *Queries) ListDocumentsByClientExternalId(ctx context.Context, clientid string) ([]*ListDocumentsByClientExternalIdRow, error) { rows, err := q.db.Query(ctx, listDocumentsByClientExternalId, clientid) if err != nil { @@ -195,7 +244,7 @@ func (q *Queries) ListDocumentsByClientExternalId(ctx context.Context, clientid items := []*ListDocumentsByClientExternalIdRow{} for rows.Next() { var i ListDocumentsByClientExternalIdRow - if err := rows.Scan(&i.ID, &i.Bucket, &i.Key); err != nil { + if err := rows.Scan(&i.ID, &i.Hash); err != nil { return nil, err } items = append(items, &i) diff --git a/internal/database/repository/document_test.go b/internal/database/repository/document_test.go index dd321b6e..62d4deaf 100644 --- a/internal/database/repository/document_test.go +++ b/internal/database/repository/document_test.go @@ -2,8 +2,6 @@ package repository_test import ( "context" - "os" - "path" "testing" "queryorchestration/internal/database/repository" @@ -11,6 +9,7 @@ import ( "queryorchestration/internal/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestDocument(t *testing.T) { @@ -20,8 +19,7 @@ func TestDocument(t *testing.T) { ctx := context.Background() cfg := &serviceconfig.BaseConfig{} - test.SetCfgProvider(t, cfg) - cfg.SetBasePath(path.Join(os.Getenv("PWD"), "../../..")) + test.SetCfgProviderWithBasePath(t, cfg, "../../..") _, cleanup := test.CreateDB(t, ctx, &test.CreateDatabaseConfig{ Cfg: cfg, RunMigrations: true, @@ -35,10 +33,10 @@ func TestDocument(t *testing.T) { Name: "example_name", Externalid: externalId, }) - assert.NoError(t, err) + require.NoError(t, err) docs, err := queries.ListDocumentsByClientExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, docs, 0) hash := "example_hash" @@ -46,7 +44,7 @@ func TestDocument(t *testing.T) { Clientid: clientId, Hash: hash, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, id) bucketone := "bucketone" @@ -56,19 +54,18 @@ func TestDocument(t *testing.T) { Bucket: bucketone, Key: keyone, }) - assert.NoError(t, err) + require.NoError(t, err) docs, err = queries.ListDocumentsByClientExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, docs, 1) - assert.Equal(t, bucketone, docs[0].Bucket) - assert.Equal(t, keyone, docs[0].Key) + assert.Equal(t, hash, docs[0].Hash) documentTwoID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: "example_hash_two", }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, documentTwoID) buckettwo := "buckettwo" @@ -78,10 +75,10 @@ func TestDocument(t *testing.T) { Bucket: buckettwo, Key: keytwo, }) - assert.NoError(t, err) + require.NoError(t, err) docs, err = queries.ListDocumentsByClientExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, docs, 2) externalTwoId := "EXAMPLE TWO" @@ -89,20 +86,20 @@ func TestDocument(t *testing.T) { Name: "example_name_two", Externalid: externalTwoId, }) - assert.NoError(t, err) + require.NoError(t, err) docs, err = queries.ListDocumentsByClientExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, docs, 2) docs, err = queries.ListDocumentsByClientExternalId(ctx, externalTwoId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, docs, 0) documentThreeId, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientTwoId, - Hash: "example_hash", + Hash: hash, }) - assert.NoError(t, err) + require.NoError(t, err) bucketthree := "buckettwo" keythree := "keytwo" @@ -111,34 +108,42 @@ func TestDocument(t *testing.T) { Bucket: bucketthree, Key: keythree, }) - assert.NoError(t, err) + require.NoError(t, err) docs, err = queries.ListDocumentsByClientExternalId(ctx, externalId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, docs, 2) docs, err = queries.ListDocumentsByClientExternalId(ctx, externalTwoId) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, docs, 1) - assert.Equal(t, bucketthree, docs[0].Bucket) - assert.Equal(t, keythree, docs[0].Key) + assert.Equal(t, hash, docs[0].Hash) - doc, err := queries.GetDocument(ctx, id) - assert.NoError(t, err) + doc, err := queries.GetDocumentSummary(ctx, id) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Document{ ID: id, Clientid: clientId, Hash: hash, }, doc) + docext, err := queries.GetDocumentExternal(ctx, id) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: id, + Clientid: externalId, + Hash: hash, + Fields: []byte("{}"), + }, docext) + docid, err := queries.GetDocumentIDByHash(ctx, &repository.GetDocumentIDByHashParams{ Hash: hash, Clientid: clientId, }) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, id, docid) entry, err := queries.GetDocumentEntry(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.GetDocumentEntryRow{ Documentid: id, Bucket: bucketone, @@ -146,7 +151,7 @@ func TestDocument(t *testing.T) { }, entry) entry, err = queries.GetDocumentEntry(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.GetDocumentEntryRow{ Documentid: documentTwoID, Bucket: buckettwo, @@ -154,7 +159,7 @@ func TestDocument(t *testing.T) { }, entry) entry, err = queries.GetDocumentEntry(ctx, documentThreeId) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.GetDocumentEntryRow{ Documentid: documentThreeId, Bucket: bucketthree, diff --git a/internal/database/repository/failtype_test.go b/internal/database/repository/failtype_test.go index 890b35dc..875b1a5b 100644 --- a/internal/database/repository/failtype_test.go +++ b/internal/database/repository/failtype_test.go @@ -7,6 +7,7 @@ import ( "queryorchestration/internal/database/repository" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestFailTypeScan(t *testing.T) { @@ -14,7 +15,7 @@ func TestFailTypeScan(t *testing.T) { stringType := "invalid_mimetype" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) } func TestNullFailTypeScan(t *testing.T) { @@ -22,7 +23,7 @@ func TestNullFailTypeScan(t *testing.T) { stringType := "invalid_mimetype" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) } func TestNullFailTypeValue(t *testing.T) { @@ -30,10 +31,10 @@ func TestNullFailTypeValue(t *testing.T) { stringType := "invalid_mimetype" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) val, err := qType.Value() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, stringType, val) } diff --git a/internal/database/repository/job_test.go b/internal/database/repository/job_test.go deleted file mode 100644 index 1366ecf3..00000000 --- a/internal/database/repository/job_test.go +++ /dev/null @@ -1,587 +0,0 @@ -package repository_test - -import ( - "context" - "os" - "path" - "testing" - - "queryorchestration/internal/database/repository" - "queryorchestration/internal/serviceconfig" - "queryorchestration/internal/test" - - "github.com/stretchr/testify/assert" -) - -func TestListClientDocumentIDs(t *testing.T) { - if testing.Short() { - t.Skip("Skipping long test in short mode") - } - ctx := context.Background() - - cfg := &serviceconfig.BaseConfig{} - test.SetCfgProvider(t, cfg) - cfg.SetBasePath(path.Join(os.Getenv("PWD"), "../../..")) - _, cleanup := test.CreateDB(t, ctx, &test.CreateDatabaseConfig{ - Cfg: cfg, - RunMigrations: true, - }) - defer cleanup() - - queries := cfg.GetDBQueries() - - id, err := queries.CreateClient(ctx, &repository.CreateClientParams{ - Name: "example_client", - Externalid: "EXAMPLE", - }) - assert.NoError(t, err) - - ids, err := queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ - Clientid: id, - Batchsize: 1, - Pageoffset: 0, - }) - assert.NoError(t, err) - assert.Len(t, ids, 0) - - docOne, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ - Clientid: id, - Hash: "example_hash", - }) - assert.NoError(t, err) - - ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ - Clientid: id, - Batchsize: 1, - Pageoffset: 0, - }) - assert.NoError(t, err) - assert.Len(t, ids, 1) - total := int64(1) - assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ - { - ID: docOne, - Totalcount: &total, - }, - }, ids) - - docTwo, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ - Clientid: id, - Hash: "example_hash_two", - }) - assert.NoError(t, err) - - ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ - Clientid: id, - Batchsize: 1, - Pageoffset: 0, - }) - assert.NoError(t, err) - assert.Len(t, ids, 1) - total = int64(2) - assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ - { - ID: docOne, - Totalcount: &total, - }, - }, ids) - - ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ - Clientid: id, - Batchsize: 1, - Pageoffset: 1, - }) - assert.NoError(t, err) - assert.Len(t, ids, 1) - assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ - { - ID: docTwo, - Totalcount: &total, - }, - }, ids) - - ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ - Clientid: id, - Batchsize: 2, - Pageoffset: 0, - }) - assert.NoError(t, err) - assert.Len(t, ids, 2) - assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ - { - ID: docOne, - Totalcount: &total, - }, - { - ID: docTwo, - Totalcount: &total, - }, - }, ids) -} - -func TestClientSync(t *testing.T) { - if testing.Short() { - t.Skip("Skipping long test in short mode") - } - ctx := context.Background() - - cfg := &serviceconfig.BaseConfig{} - test.SetCfgProvider(t, cfg) - cfg.SetBasePath(path.Join(os.Getenv("PWD"), "../../..")) - _, cleanup := test.CreateDB(t, ctx, &test.CreateDatabaseConfig{ - Cfg: cfg, - RunMigrations: true, - }) - defer cleanup() - - queries := cfg.GetDBQueries() - - contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) - assert.NoError(t, err) - _, err = queries.AddLatestQueryVersion(ctx, contextQueryID) - assert.NoError(t, err) - err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ - Queryid: contextQueryID, - Versionid: 1, - }) - assert.NoError(t, err) - jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) - _, err = queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) - err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ - Queryid: jsonQueryID, - Versionid: 1, - }) - assert.NoError(t, err) - err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ - Queryid: jsonQueryID, - Requiredqueryid: contextQueryID, - Addedversion: 1, - }) - assert.NoError(t, err) - - clientId, err := queries.CreateClient(ctx, &repository.CreateClientParams{ - Name: "example_client", - Externalid: "EXAMPLE", - }) - assert.NoError(t, err) - - _, err = queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) - err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ - Versionid: 1, - Clientid: clientId, - }) - assert.NoError(t, err) - err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ - Clientid: clientId, - Queryid: jsonQueryID, - Addedversion: 1, - Name: "example_key", - }) - assert.NoError(t, err) - - isSynced, err := queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - documentNoCleanID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ - Clientid: clientId, - Hash: "example_noclean", - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - bucket := "example_bucket" - key := "example_key" - cleanid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ - Documentid: documentNoCleanID, - Fail: repository.NullCleanfailtype{ - Valid: true, - Cleanfailtype: repository.CleanfailtypeInvalidMimetype, - }, - }) - assert.NoError(t, err) - err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ - Cleanid: cleanid, - Version: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ - Clientid: clientId, - Hash: "example_hash", - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - keytwo := "example_key_2" - cleantwoid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ - Documentid: documentID, - Bucket: &bucket, - Key: &keytwo, - Mimetype: repository.NullCleanmimetype{ - Valid: true, - Cleanmimetype: repository.CleanmimetypeApplicationPdf, - }, - }) - assert.NoError(t, err) - err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ - Cleanid: cleantwoid, - Version: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ - Version: 1, - Bucket: "hi", - Key: "hello", - Cleanentryid: cleantwoid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - textentry, err := queries.GetTextEntryByDocId(ctx, documentID) - assert.NoError(t, err) - - depresultid, err := queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: contextQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - resultid, err := queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: jsonQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ - Resultid: resultid, - Requiredresultid: depresultid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - _, err = queries.AddLatestQueryVersion(ctx, contextQueryID) - assert.NoError(t, err) - err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ - Queryid: contextQueryID, - Versionid: 2, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - depresultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: contextQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 2, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - resultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: jsonQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ - Resultid: resultid, - Requiredresultid: depresultid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ - Version: 1, - Bucket: "hi", - Key: "hello", - Cleanentryid: cleantwoid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - textentry, err = queries.GetTextEntryByDocId(ctx, documentID) - assert.NoError(t, err) - - depresultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: contextQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 2, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - resultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: jsonQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ - Resultid: resultid, - Requiredresultid: depresultid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - cleanthreeid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ - Documentid: documentID, - Bucket: &bucket, - Key: &key, - Mimetype: repository.NullCleanmimetype{ - Valid: true, - Cleanmimetype: repository.CleanmimetypeApplicationPdf, - }, - }) - assert.NoError(t, err) - err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ - Cleanid: cleanthreeid, - Version: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ - Version: 1, - Bucket: "hi", - Key: "hello", - Cleanentryid: cleanthreeid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - textentry, err = queries.GetTextEntryByDocId(ctx, documentID) - assert.NoError(t, err) - - depresultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: contextQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 2, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - resultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: jsonQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ - Resultid: resultid, - Requiredresultid: depresultid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - _, err = queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - collversion := int32(2) - err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ - Versionid: 2, - Clientid: clientId, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - err = queries.RemoveCollectorQuery(ctx, &repository.RemoveCollectorQueryParams{ - Clientid: clientId, - Queryid: jsonQueryID, - Removedversion: &collversion, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ - Clientid: clientId, - Queryid: jsonQueryID, - Addedversion: 2, - Name: "second_key", - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ - Clientid: clientId, - Queryid: contextQueryID, - Addedversion: 2, - Name: "example_key", - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) - - superQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) - _, err = queries.AddLatestQueryVersion(ctx, superQueryID) - assert.NoError(t, err) - err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ - Queryid: superQueryID, - Versionid: 1, - }) - assert.NoError(t, err) - err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ - Queryid: contextQueryID, - Requiredqueryid: superQueryID, - Addedversion: 1, - }) - assert.NoError(t, err) - - superresultid, err := queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: superQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - depresultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: contextQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 2, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - resultid, err = queries.AddResult(ctx, &repository.AddResultParams{ - Queryid: jsonQueryID, - Value: "example_value", - Textentryid: textentry.ID, - Queryversion: 1, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ - Resultid: resultid, - Requiredresultid: depresultid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.False(t, isSynced) - - err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ - Resultid: depresultid, - Requiredresultid: superresultid, - }) - assert.NoError(t, err) - - isSynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) - assert.True(t, isSynced) -} diff --git a/internal/database/repository/mimetype_test.go b/internal/database/repository/mimetype_test.go index fae57fd0..0c8ee0c0 100644 --- a/internal/database/repository/mimetype_test.go +++ b/internal/database/repository/mimetype_test.go @@ -7,6 +7,7 @@ import ( "queryorchestration/internal/database/repository" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMimeTypeScan(t *testing.T) { @@ -14,7 +15,7 @@ func TestMimeTypeScan(t *testing.T) { stringType := "application/pdf" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) } func TestNullMimeTypeScan(t *testing.T) { @@ -22,7 +23,7 @@ func TestNullMimeTypeScan(t *testing.T) { stringType := "application/pdf" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) } func TestNullMimeTypeValue(t *testing.T) { @@ -30,10 +31,10 @@ func TestNullMimeTypeValue(t *testing.T) { stringType := "application/pdf" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) val, err := qType.Value() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, stringType, val) } diff --git a/internal/database/repository/query_test.go b/internal/database/repository/query_test.go index defec16a..9ddb7d03 100644 --- a/internal/database/repository/query_test.go +++ b/internal/database/repository/query_test.go @@ -14,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestQueries(t *testing.T) { @@ -34,11 +35,11 @@ func TestQueries(t *testing.T) { queries := cfg.GetDBQueries() contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, contextQueryID.Valid) contextQuery, err := queries.GetQuery(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: contextQueryID, Type: repository.QuerytypeContextFull, @@ -49,11 +50,11 @@ func TestQueries(t *testing.T) { }, contextQuery) ctxVersion, err := queries.AddLatestQueryVersion(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int32(1), ctxVersion) contextQuery, err = queries.GetQuery(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: contextQueryID, Type: repository.QuerytypeContextFull, @@ -64,11 +65,11 @@ func TestQueries(t *testing.T) { }, contextQuery) jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, jsonQueryID.Valid) jsonQuery, err := queries.GetQuery(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: jsonQueryID, Type: repository.QuerytypeJsonExtractor, @@ -79,11 +80,11 @@ func TestQueries(t *testing.T) { }, jsonQuery) jsonVersion, err := queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int32(1), jsonVersion) jsonQuery, err = queries.GetQuery(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: jsonQueryID, Type: repository.QuerytypeJsonExtractor, @@ -97,10 +98,10 @@ func TestQueries(t *testing.T) { Versionid: 1, Queryid: jsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) jsonQuery, err = queries.GetQuery(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: jsonQueryID, Type: repository.QuerytypeJsonExtractor, @@ -117,10 +118,10 @@ func TestQueries(t *testing.T) { Requiredqueryid: contextQueryID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) jsonQuery, err = queries.GetQuery(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: jsonQueryID, Type: repository.QuerytypeJsonExtractor, @@ -131,11 +132,11 @@ func TestQueries(t *testing.T) { }, jsonQuery) jsonVersion, err = queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int32(2), jsonVersion) jsonQuery, err = queries.GetQuery(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: jsonQueryID, Type: repository.QuerytypeJsonExtractor, @@ -151,17 +152,17 @@ func TestQueries(t *testing.T) { Requiredqueryid: contextQueryID, Removedversion: &removeV, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetQueryConfig(ctx, &repository.SetQueryConfigParams{ Queryid: jsonQueryID, Config: jsonConfig, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) jsonQueryConfig, err := queries.GetActiveQueryConfig(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, jsonConfig, jsonQueryConfig) err = queries.SetQueryConfig(ctx, &repository.SetQueryConfigParams{ @@ -169,24 +170,24 @@ func TestQueries(t *testing.T) { Config: []byte(`{"second":"key"}`), Addedversion: 2, }) - assert.NoError(t, err) + require.NoError(t, err) jsonQueryConfig, err = queries.GetActiveQueryConfig(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, jsonConfig, jsonQueryConfig) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: jsonQueryID, Versionid: 2, }) - assert.NoError(t, err) + require.NoError(t, err) jsonQueryConfig, err = queries.GetActiveQueryConfig(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []byte(`{"second": "key"}`), jsonQueryConfig) jsonQuery, err = queries.GetQuery(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.Fullactivequery{ ID: jsonQueryID, Type: repository.QuerytypeJsonExtractor, @@ -201,7 +202,7 @@ func TestQueries(t *testing.T) { ID: jsonQueryID, Version: &v, }) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &repository.GetQueryWithVersionRow{ ID: jsonQueryID, Type: repository.QuerytypeJsonExtractor, @@ -212,23 +213,23 @@ func TestQueries(t *testing.T) { }, versionedQuery) all_exist, err := queries.AllQueriesExist(ctx, []pgtype.UUID{}) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, all_exist) all_exist, err = queries.AllQueriesExist(ctx, []pgtype.UUID{database.MustToDBUUID(uuid.New())}) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, all_exist) all_exist, err = queries.AllQueriesExist(ctx, []pgtype.UUID{jsonQueryID}) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, all_exist) all_exist, err = queries.AllQueriesExist(ctx, []pgtype.UUID{jsonQueryID, contextQueryID}) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, all_exist) all_exist, err = queries.AllQueriesExist(ctx, []pgtype.UUID{jsonQueryID, database.MustToDBUUID(uuid.New())}) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, all_exist) } @@ -253,52 +254,52 @@ func TestQueryDependencyTree(t *testing.T) { Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) version, err := queries.AddLatestCollectorVersion(ctx, clientID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Clientid: clientID, Versionid: version, }) - assert.NoError(t, err) + require.NoError(t, err) docID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientID, Hash: "sample", }) - assert.NoError(t, err) + require.NoError(t, err) contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: contextQueryID, Versionid: 1, }) - assert.NoError(t, err) + require.NoError(t, err) dependents, err := queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: contextQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: jsonQueryID, Versionid: 1, }) - assert.NoError(t, err) + require.NoError(t, err) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: jsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ @@ -306,19 +307,19 @@ func TestQueryDependencyTree(t *testing.T) { Requiredqueryid: contextQueryID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: jsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: contextQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ @@ -327,42 +328,42 @@ func TestQueryDependencyTree(t *testing.T) { Queryid: jsonQueryID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: jsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: contextQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, dependents) secondJsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, secondJsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: secondJsonQueryID, Versionid: 1, }) - assert.NoError(t, err) + require.NoError(t, err) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: jsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: contextQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, dependents) err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ @@ -370,25 +371,25 @@ func TestQueryDependencyTree(t *testing.T) { Requiredqueryid: jsonQueryID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: secondJsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: jsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: contextQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, dependents) err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ @@ -397,60 +398,60 @@ func TestQueryDependencyTree(t *testing.T) { Queryid: secondJsonQueryID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: secondJsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, dependents) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: jsonQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{secondJsonQueryID}, dependents) dependents, err = queries.ListQueryDirectDependentsByDocumentID(ctx, &repository.ListQueryDirectDependentsByDocumentIDParams{ Documentid: docID, Queryid: contextQueryID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, dependents) isdependent, err := queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{ Queryid: jsonQueryID, Requiredqueryids: []pgtype.UUID{contextQueryID}, }) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, isdependent) isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{ Queryid: jsonQueryID, Requiredqueryids: []pgtype.UUID{secondJsonQueryID}, }) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, isdependent) isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{ Queryid: jsonQueryID, Requiredqueryids: []pgtype.UUID{jsonQueryID}, }) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, isdependent) isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{ Queryid: secondJsonQueryID, Requiredqueryids: []pgtype.UUID{jsonQueryID, contextQueryID}, }) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, isdependent) isdependent, err = queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{ Queryid: contextQueryID, Requiredqueryids: []pgtype.UUID{jsonQueryID, secondJsonQueryID}, }) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, isdependent) } @@ -472,13 +473,13 @@ func TestQueriesList(t *testing.T) { queries := cfg.GetDBQueries() contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) - assert.NoError(t, err) + require.NoError(t, err) jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) qs, err := queries.ListQueries(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 2) assert.ElementsMatch(t, []*repository.Fullactivequery{ { @@ -500,7 +501,7 @@ func TestQueriesList(t *testing.T) { }, qs) qs, err = queries.ListQueriesById(ctx, []pgtype.UUID{jsonQueryID}) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 1) assert.ElementsMatch(t, []*repository.Fullactivequery{ { @@ -532,79 +533,79 @@ func TestListQueryClients(t *testing.T) { queries := cfg.GetDBQueries() contextID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) - assert.NoError(t, err) + require.NoError(t, err) clients, err := queries.ListQueryClientIDs(ctx, contextID) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{}, clients) clientOneID, err := queries.CreateClient(ctx, &repository.CreateClientParams{ Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) versionOne, err := queries.AddLatestCollectorVersion(ctx, clientOneID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Clientid: clientOneID, Versionid: versionOne, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ Clientid: clientOneID, Queryid: contextID, Addedversion: 1, Name: "example_key", }) - assert.NoError(t, err) + require.NoError(t, err) clients, err = queries.ListQueryClientIDs(ctx, contextID) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{clientOneID}, clients) clientTwoID, err := queries.CreateClient(ctx, &repository.CreateClientParams{ Name: "example_client_dos", Externalid: "EXAMPLE DOS", }) - assert.NoError(t, err) + require.NoError(t, err) versionTwo, err := queries.AddLatestCollectorVersion(ctx, clientTwoID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Clientid: clientTwoID, Versionid: versionTwo, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ Clientid: clientTwoID, Queryid: contextID, Addedversion: 1, Name: "example_key", }) - assert.NoError(t, err) + require.NoError(t, err) clients, err = queries.ListQueryClientIDs(ctx, contextID) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{clientOneID, clientTwoID}, clients) jsonID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, jsonID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ Queryid: jsonID, Requiredqueryid: contextID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ Clientid: clientOneID, Queryid: jsonID, Addedversion: 1, Name: "example_key", }) - assert.NoError(t, err) + require.NoError(t, err) clients, err = queries.ListQueryClientIDs(ctx, jsonID) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []pgtype.UUID{clientOneID}, clients) } diff --git a/internal/database/repository/querytype_test.go b/internal/database/repository/querytype_test.go index ad74d4d9..aac36288 100644 --- a/internal/database/repository/querytype_test.go +++ b/internal/database/repository/querytype_test.go @@ -7,6 +7,7 @@ import ( "queryorchestration/internal/database/repository" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestQueryTypeScan(t *testing.T) { @@ -14,7 +15,7 @@ func TestQueryTypeScan(t *testing.T) { stringType := "context_full" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) } func TestNullQueryTypeScan(t *testing.T) { @@ -22,7 +23,7 @@ func TestNullQueryTypeScan(t *testing.T) { stringType := "context_full" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) } func TestNullQueryTypeValue(t *testing.T) { @@ -30,10 +31,10 @@ func TestNullQueryTypeValue(t *testing.T) { stringType := "context_full" err := qType.Scan(stringType) - assert.NoError(t, err) + require.NoError(t, err) val, err := qType.Value() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, stringType, val) } diff --git a/internal/database/repository/result_test.go b/internal/database/repository/result_test.go index 6639115e..c5983e13 100644 --- a/internal/database/repository/result_test.go +++ b/internal/database/repository/result_test.go @@ -12,6 +12,7 @@ import ( "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestResults(t *testing.T) { @@ -32,45 +33,45 @@ func TestResults(t *testing.T) { queries := cfg.GetDBQueries() jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: jsonQueryID, Versionid: 1, }) - assert.NoError(t, err) + require.NoError(t, err) clientId, err := queries.CreateClient(ctx, &repository.CreateClientParams{ Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) issynced, err := queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, issynced) documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: "example_hash", }) - assert.NoError(t, err) + require.NoError(t, err) issynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, issynced) version, err := queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Versionid: version, Clientid: clientId, }) - assert.NoError(t, err) + require.NoError(t, err) issynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, issynced) bucket := "example_bucket" @@ -84,42 +85,39 @@ func TestResults(t *testing.T) { Cleanmimetype: repository.CleanmimetypeApplicationPdf, }, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Cleanid: cleanid, Version: 1, }) - assert.NoError(t, err) + require.NoError(t, err) issynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, issynced) - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + textId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ Version: 1, Bucket: "hi", Key: "hello", Cleanentryid: cleanid, }) - assert.NoError(t, err) + require.NoError(t, err) issynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, issynced) - textentry, err := queries.GetTextEntryByDocId(ctx, documentID) - assert.NoError(t, err) - err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ Clientid: clientId, Queryid: jsonQueryID, Addedversion: 1, Name: "example_key", }) - assert.NoError(t, err) + require.NoError(t, err) issynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, issynced) jsonResultValue := "example_value" @@ -127,13 +125,13 @@ func TestResults(t *testing.T) { _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: jsonQueryID, Value: jsonResultValue, - Textentryid: textentry.ID, + Textentryid: textId, Queryversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) issynced, err = queries.IsClientSynced(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, issynced) qv := int32(1) @@ -142,7 +140,7 @@ func TestResults(t *testing.T) { Queryversion: &qv, Documentid: documentID, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, res.Value) assert.Equal(t, jsonResultValue, *res.Value) } @@ -165,43 +163,43 @@ func TestResultValues(t *testing.T) { queries := cfg.GetDBQueries() jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) clientId, err := queries.CreateClient(ctx, &repository.CreateClientParams{ Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: "example_hash", }) - assert.NoError(t, err) + require.NoError(t, err) documentTwoID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: "example_hash_two", }) - assert.NoError(t, err) + require.NoError(t, err) contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: jsonQueryID, Versionid: 1, }) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: contextQueryID, Versionid: 2, }) - assert.NoError(t, err) + require.NoError(t, err) jsonVersion := int32(1) err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ @@ -209,33 +207,33 @@ func TestResultValues(t *testing.T) { Requiredqueryid: contextQueryID, Addedversion: jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) contextQuery, err := queries.GetQuery(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) qResults, err := queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{ Queryid: jsonQueryID, Documentid: documentID, Version: &jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qResults, 0) qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{ Queryid: jsonQueryID, Documentid: documentTwoID, Version: &jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qResults, 0) version, err := queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Versionid: version, Clientid: clientId, }) - assert.NoError(t, err) + require.NoError(t, err) bucket := "example_bucket" key := "example_key" @@ -248,38 +246,36 @@ func TestResultValues(t *testing.T) { Cleanmimetype: repository.CleanmimetypeApplicationPdf, }, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Cleanid: cleanid, Version: 1, }) - assert.NoError(t, err) - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + require.NoError(t, err) + textId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ Version: 1, Bucket: "hi", Key: "hello", Cleanentryid: cleanid, }) - assert.NoError(t, err) - textentry, err := queries.GetTextEntryByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) result := repository.AddResultParams{ Queryid: contextQueryID, Value: "context_value_1", - Textentryid: textentry.ID, + Textentryid: textId, Queryversion: contextQuery.Activeversion, } _, err = queries.AddResult(ctx, &result) - assert.NoError(t, err) + require.NoError(t, err) qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{ Queryid: jsonQueryID, Documentid: documentID, Version: &jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qResults, 1) assert.Equal(t, contextQueryID, qResults[0].Queryid) assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Type) @@ -291,23 +287,23 @@ func TestResultValues(t *testing.T) { Documentid: documentTwoID, Version: &jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qResults, 0) _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: contextQueryID, Value: "context_value_2", - Textentryid: textentry.ID, + Textentryid: textId, Queryversion: contextQuery.Activeversion - 1, }) - assert.NoError(t, err) + require.NoError(t, err) qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{ Queryid: jsonQueryID, Documentid: documentID, Version: &jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qResults, 1) assert.Equal(t, contextQueryID, qResults[0].Queryid) assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Type) @@ -318,17 +314,17 @@ func TestResultValues(t *testing.T) { _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: contextQueryID, Value: "context_value_3", - Textentryid: textentry.ID, + Textentryid: textId, Queryversion: contextQuery.Activeversion, }) - assert.NoError(t, err) + require.NoError(t, err) qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{ Queryid: jsonQueryID, Documentid: documentID, Version: &jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qResults, 1) assert.Equal(t, contextQueryID, qResults[0].Queryid) assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Type) @@ -339,17 +335,17 @@ func TestResultValues(t *testing.T) { _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: jsonQueryID, Value: "json_value_1", - Textentryid: textentry.ID, + Textentryid: textId, Queryversion: jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) qResults, err = queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{ Queryid: jsonQueryID, Documentid: documentID, Version: &jsonVersion, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qResults, 1) assert.Equal(t, contextQueryID, qResults[0].Queryid) assert.Equal(t, repository.QuerytypeContextFull, qResults[0].Type) @@ -379,49 +375,49 @@ func TestUnsyncedNoDepsQueries(t *testing.T) { Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) version, err := queries.AddLatestCollectorVersion(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ Versionid: version, Clientid: clientId, }) - assert.NoError(t, err) + require.NoError(t, err) documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: "example_hash", }) - assert.NoError(t, err) + require.NoError(t, err) documentTwoID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: "example_hash_two", }) - assert.NoError(t, err) + require.NoError(t, err) contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) - assert.NoError(t, err) + require.NoError(t, err) jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: jsonQueryID, Versionid: 1, }) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddLatestQueryVersion(ctx, contextQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: contextQueryID, Versionid: 1, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ Queryid: jsonQueryID, Requiredqueryid: contextQueryID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ Clientid: clientId, @@ -429,13 +425,13 @@ func TestUnsyncedNoDepsQueries(t *testing.T) { Queryid: jsonQueryID, Addedversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err := queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) bucket := "example_bucket" @@ -449,68 +445,65 @@ func TestUnsyncedNoDepsQueries(t *testing.T) { Cleanmimetype: repository.CleanmimetypeApplicationPdf, }, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Cleanid: cleanid, Version: 1, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + textId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ Version: 1, Bucket: "hi", Key: "hello", Cleanentryid: cleanid, }) - assert.NoError(t, err) - - textentry, err := queries.GetTextEntryByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 1) assert.ElementsMatch(t, []pgtype.UUID{contextQueryID}, qs) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: contextQueryID, Value: "context_value", - Textentryid: textentry.ID, + Textentryid: textId, Queryversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 1) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, qs) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: jsonQueryID, Value: "context_value", - Textentryid: textentry.ID, + Textentryid: textId, Queryversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) cleantwoid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ @@ -522,76 +515,73 @@ func TestUnsyncedNoDepsQueries(t *testing.T) { Cleanmimetype: repository.CleanmimetypeApplicationPdf, }, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Cleanid: cleantwoid, Version: 1, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + textTwoId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ Version: 1, Bucket: "hi", Key: "hello", Cleanentryid: cleantwoid, }) - assert.NoError(t, err) - - texttwoentry, err := queries.GetTextEntryByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: contextQueryID, Value: "context_value", - Textentryid: texttwoentry.ID, + Textentryid: textTwoId, Queryversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 1) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, qs) _, err = queries.AddResult(ctx, &repository.AddResultParams{ Queryid: jsonQueryID, Value: "context_value", - Textentryid: texttwoentry.ID, + Textentryid: textTwoId, Queryversion: 1, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 0) _, err = queries.AddLatestQueryVersion(ctx, jsonQueryID) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ Queryid: jsonQueryID, Versionid: 2, }) - assert.NoError(t, err) + require.NoError(t, err) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 1) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, qs) qs, err = queries.ListUnsyncedNoDepsQueriesByDocId(ctx, documentTwoID) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, qs, 1) assert.ElementsMatch(t, []pgtype.UUID{jsonQueryID}, qs) } diff --git a/internal/database/repository/sync_test.go b/internal/database/repository/sync_test.go new file mode 100644 index 00000000..8506bdad --- /dev/null +++ b/internal/database/repository/sync_test.go @@ -0,0 +1,847 @@ +package repository_test + +import ( + "context" + "os" + "path" + "testing" + + "queryorchestration/internal/database/repository" + "queryorchestration/internal/serviceconfig" + "queryorchestration/internal/test" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestListClientDocumentIDs(t *testing.T) { + if testing.Short() { + t.Skip("Skipping long test in short mode") + } + ctx := context.Background() + + cfg := &serviceconfig.BaseConfig{} + test.SetCfgProvider(t, cfg) + cfg.SetBasePath(path.Join(os.Getenv("PWD"), "../../..")) + _, cleanup := test.CreateDB(t, ctx, &test.CreateDatabaseConfig{ + Cfg: cfg, + RunMigrations: true, + }) + defer cleanup() + + queries := cfg.GetDBQueries() + + id, err := queries.CreateClient(ctx, &repository.CreateClientParams{ + Name: "example_client", + Externalid: "EXAMPLE", + }) + require.NoError(t, err) + + ids, err := queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ + Clientid: id, + Batchsize: 1, + Pageoffset: 0, + }) + require.NoError(t, err) + assert.Len(t, ids, 0) + + docOne, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ + Clientid: id, + Hash: "example_hash", + }) + require.NoError(t, err) + + ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ + Clientid: id, + Batchsize: 1, + Pageoffset: 0, + }) + require.NoError(t, err) + assert.Len(t, ids, 1) + total := int64(1) + assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ + { + ID: docOne, + Totalcount: &total, + }, + }, ids) + + docTwo, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ + Clientid: id, + Hash: "example_hash_two", + }) + require.NoError(t, err) + + ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ + Clientid: id, + Batchsize: 1, + Pageoffset: 0, + }) + require.NoError(t, err) + assert.Len(t, ids, 1) + total = int64(2) + assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ + { + ID: docOne, + Totalcount: &total, + }, + }, ids) + + ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ + Clientid: id, + Batchsize: 1, + Pageoffset: 1, + }) + require.NoError(t, err) + assert.Len(t, ids, 1) + assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ + { + ID: docTwo, + Totalcount: &total, + }, + }, ids) + + ids, err = queries.ListDocumentIDsBatch(ctx, &repository.ListDocumentIDsBatchParams{ + Clientid: id, + Batchsize: 2, + Pageoffset: 0, + }) + require.NoError(t, err) + assert.Len(t, ids, 2) + assert.ElementsMatch(t, []*repository.ListDocumentIDsBatchRow{ + { + ID: docOne, + Totalcount: &total, + }, + { + ID: docTwo, + Totalcount: &total, + }, + }, ids) +} + +func TestClientSync(t *testing.T) { + if testing.Short() { + t.Skip("Skipping long test in short mode") + } + ctx := context.Background() + + cfg := &serviceconfig.BaseConfig{} + test.SetCfgProvider(t, cfg) + cfg.SetBasePath(path.Join(os.Getenv("PWD"), "../../..")) + _, cleanup := test.CreateDB(t, ctx, &test.CreateDatabaseConfig{ + Cfg: cfg, + RunMigrations: true, + }) + defer cleanup() + + queries := cfg.GetDBQueries() + + contextQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeContextFull)) + require.NoError(t, err) + contextQueryVersion, err := queries.AddLatestQueryVersion(ctx, contextQueryID) + require.NoError(t, err) + err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ + Queryid: contextQueryID, + Versionid: contextQueryVersion, + }) + require.NoError(t, err) + jsonQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) + require.NoError(t, err) + jsonQueryVersion, err := queries.AddLatestQueryVersion(ctx, jsonQueryID) + require.NoError(t, err) + err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ + Queryid: jsonQueryID, + Versionid: jsonQueryVersion, + }) + require.NoError(t, err) + err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ + Queryid: jsonQueryID, + Requiredqueryid: contextQueryID, + Addedversion: jsonQueryVersion, + }) + require.NoError(t, err) + + externalId := "EXAMPLE" + clientId, err := queries.CreateClient(ctx, &repository.CreateClientParams{ + Name: "example_client", + Externalid: externalId, + }) + require.NoError(t, err) + + collectorVersion, err := queries.AddLatestCollectorVersion(ctx, clientId) + require.NoError(t, err) + err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ + Versionid: collectorVersion, + Clientid: clientId, + }) + require.NoError(t, err) + err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ + Clientid: clientId, + Queryid: jsonQueryID, + Addedversion: collectorVersion, + Name: "first_key", + }) + require.NoError(t, err) + + isSynced, err := queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + + bucket := "example_bucket" + + t.Run("document fail clean", func(t *testing.T) { + documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ + Clientid: clientId, + Hash: "example_noclean", + }) + require.NoError(t, err) + + docExternal, err := queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_noclean", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + + cleanid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ + Documentid: documentID, + Fail: repository.NullCleanfailtype{ + Valid: true, + Cleanfailtype: repository.CleanfailtypeInvalidMimetype, + }, + }) + require.NoError(t, err) + err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ + Cleanid: cleanid, + Version: 1, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_noclean", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + }) + + t.Run("valid extraction", func(t *testing.T) { + documentID, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ + Clientid: clientId, + Hash: "example_hash", + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + + docExternal, err := queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + key := "example_key" + cleanId, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ + Documentid: documentID, + Bucket: &bucket, + Key: &key, + Mimetype: repository.NullCleanmimetype{ + Valid: true, + Cleanmimetype: repository.CleanmimetypeApplicationPdf, + }, + }) + require.NoError(t, err) + err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ + Cleanid: cleanId, + Version: 1, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + textId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + Version: 1, + Bucket: "hi", + Key: "hello", + Cleanentryid: cleanId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + t.Run("document standard results", func(t *testing.T) { + contextResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: contextQueryID, + Value: "example_context", + Textentryid: textId, + Queryversion: contextQueryVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + jsonResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: jsonQueryID, + Value: "json_value", + Textentryid: textId, + Queryversion: jsonQueryVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ + Resultid: jsonResultId, + Requiredresultid: contextResultId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": "json_value"}`), + }, docExternal) + }) + + contextLatestVersion, err := queries.AddLatestQueryVersion(ctx, contextQueryID) + require.NoError(t, err) + err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ + Queryid: contextQueryID, + Versionid: contextLatestVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + t.Run("update upstream query", func(t *testing.T) { + contextResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: contextQueryID, + Value: "context_version_2", + Textentryid: textId, + Queryversion: contextLatestVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + jsonResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: jsonQueryID, + Value: "updated_context_value", + Textentryid: textId, + Queryversion: jsonQueryVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ + Resultid: jsonResultId, + Requiredresultid: contextResultId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": "updated_context_value"}`), + }, docExternal) + }) + + t.Run("update text entry", func(t *testing.T) { + textId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + Version: 1, + Bucket: "hi", + Key: "hello", + Cleanentryid: cleanId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + contextResultID, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: contextQueryID, + Value: "updated_text_context", + Textentryid: textId, + Queryversion: 2, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + jsonResultID, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: jsonQueryID, + Value: "updated_text_json", + Textentryid: textId, + Queryversion: 1, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ + Resultid: jsonResultID, + Requiredresultid: contextResultID, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": "updated_text_json"}`), + }, docExternal) + }) + t.Run("updated clean entry", func(t *testing.T) { + cleanthreeid, err := queries.AddDocumentClean(ctx, &repository.AddDocumentCleanParams{ + Documentid: documentID, + Bucket: &bucket, + Key: &key, + Mimetype: repository.NullCleanmimetype{ + Valid: true, + Cleanmimetype: repository.CleanmimetypeApplicationPdf, + }, + }) + require.NoError(t, err) + err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ + Cleanid: cleanthreeid, + Version: 1, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + textThreeId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + Version: 1, + Bucket: "hi", + Key: "hello", + Cleanentryid: cleanthreeid, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + contextResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: contextQueryID, + Value: "update_clean_context", + Textentryid: textThreeId, + Queryversion: contextLatestVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + jsonResultID, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: jsonQueryID, + Value: "update_clean_json", + Textentryid: textThreeId, + Queryversion: 1, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": null}`), + }, docExternal) + + err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ + Resultid: jsonResultID, + Requiredresultid: contextResultId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": "update_clean_json"}`), + }, docExternal) + + latestCollectorVersion, err := queries.AddLatestCollectorVersion(ctx, clientId) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": "update_clean_json"}`), + }, docExternal) + + t.Run("update collector name", func(t *testing.T) { + err = queries.SetActiveCollectorVersion(ctx, &repository.SetActiveCollectorVersionParams{ + Versionid: latestCollectorVersion, + Clientid: clientId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"first_key": "update_clean_json"}`), + }, docExternal) + + err = queries.RemoveCollectorQuery(ctx, &repository.RemoveCollectorQueryParams{ + Clientid: clientId, + Queryid: jsonQueryID, + Removedversion: &latestCollectorVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{}`), + }, docExternal) + + err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ + Clientid: clientId, + Queryid: jsonQueryID, + Addedversion: latestCollectorVersion, + Name: "second_key", + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"second_key": "update_clean_json"}`), + }, docExternal) + }) + + t.Run("add existing query", func(t *testing.T) { + err = queries.AddCollectorQuery(ctx, &repository.AddCollectorQueryParams{ + Clientid: clientId, + Queryid: contextQueryID, + Addedversion: latestCollectorVersion, + Name: "example_key", + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"second_key": "update_clean_json", "example_key": "update_clean_context"}`), + }, docExternal) + }) + + t.Run("add super query", func(t *testing.T) { + superQueryID, err := queries.CreateQuery(ctx, repository.Querytype(repository.QuerytypeJsonExtractor)) + require.NoError(t, err) + superQueryVersion, err := queries.AddLatestQueryVersion(ctx, superQueryID) + require.NoError(t, err) + err = queries.AddActiveQueryVersion(ctx, &repository.AddActiveQueryVersionParams{ + Queryid: superQueryID, + Versionid: superQueryVersion, + }) + require.NoError(t, err) + err = queries.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{ + Queryid: contextQueryID, + Requiredqueryid: superQueryID, + Addedversion: superQueryVersion, + }) + require.NoError(t, err) + + superResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: superQueryID, + Value: "super_value", + Textentryid: textThreeId, + Queryversion: superQueryVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"second_key": null, "example_key": null}`), + }, docExternal) + + contextResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: contextQueryID, + Value: "context_with_super_value", + Textentryid: textThreeId, + Queryversion: contextLatestVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"second_key": null, "example_key": null}`), + }, docExternal) + + jsonResultId, err := queries.AddResult(ctx, &repository.AddResultParams{ + Queryid: jsonQueryID, + Value: "json_with_super", + Textentryid: textThreeId, + Queryversion: jsonQueryVersion, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"second_key": null, "example_key": null}`), + }, docExternal) + + err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ + Resultid: contextResultId, + Requiredresultid: superResultId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.False(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"second_key": null, "example_key": "context_with_super_value"}`), + }, docExternal) + + err = queries.AddResultDependency(ctx, &repository.AddResultDependencyParams{ + Resultid: jsonResultId, + Requiredresultid: contextResultId, + }) + require.NoError(t, err) + + isSynced, err = queries.IsClientSynced(ctx, clientId) + require.NoError(t, err) + assert.True(t, isSynced) + docExternal, err = queries.GetDocumentExternal(ctx, documentID) + require.NoError(t, err) + assert.EqualExportedValues(t, &repository.GetDocumentExternalRow{ + ID: documentID, + Clientid: externalId, + Hash: "example_hash", + Fields: []byte(`{"second_key": "json_with_super", "example_key": "context_with_super_value"}`), + }, docExternal) + }) + }) + }) +} diff --git a/internal/database/repository/text.sql.go b/internal/database/repository/text.sql.go index e85103b7..295b9c1a 100644 --- a/internal/database/repository/text.sql.go +++ b/internal/database/repository/text.sql.go @@ -11,8 +11,8 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -const addDocumentTextEntry = `-- name: AddDocumentTextEntry :exec -INSERT INTO documentTextExtractions (version, bucket, key, cleanEntryId) VALUES ($1, $2, $3, $4) +const addDocumentTextEntry = `-- name: AddDocumentTextEntry :one +INSERT INTO documentTextExtractions (version, bucket, key, cleanEntryId) VALUES ($1, $2, $3, $4) returning id ` type AddDocumentTextEntryParams struct { @@ -24,15 +24,17 @@ type AddDocumentTextEntryParams struct { // AddDocumentTextEntry // -// INSERT INTO documentTextExtractions (version, bucket, key, cleanEntryId) VALUES ($1, $2, $3, $4) -func (q *Queries) AddDocumentTextEntry(ctx context.Context, arg *AddDocumentTextEntryParams) error { - _, err := q.db.Exec(ctx, addDocumentTextEntry, +// INSERT INTO documentTextExtractions (version, bucket, key, cleanEntryId) VALUES ($1, $2, $3, $4) returning id +func (q *Queries) AddDocumentTextEntry(ctx context.Context, arg *AddDocumentTextEntryParams) (pgtype.UUID, error) { + row := q.db.QueryRow(ctx, addDocumentTextEntry, arg.Version, arg.Bucket, arg.Key, arg.Cleanentryid, ) - return err + var id pgtype.UUID + err := row.Scan(&id) + return id, err } const getTextEntryByDocId = `-- name: GetTextEntryByDocId :one diff --git a/internal/database/repository/text_test.go b/internal/database/repository/text_test.go index ceeac194..0ead79f3 100644 --- a/internal/database/repository/text_test.go +++ b/internal/database/repository/text_test.go @@ -12,6 +12,7 @@ import ( "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestTextExtraction(t *testing.T) { @@ -35,14 +36,14 @@ func TestTextExtraction(t *testing.T) { Name: "example_client", Externalid: "EXAMPLE", }) - assert.NoError(t, err) + require.NoError(t, err) hash := "example_hash" id, err := queries.CreateDocument(ctx, &repository.CreateDocumentParams{ Clientid: clientId, Hash: hash, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, id) bucket := "example_bucket" @@ -56,35 +57,36 @@ func TestTextExtraction(t *testing.T) { Cleanmimetype: repository.CleanmimetypeApplicationPdf, }, }) - assert.NoError(t, err) + require.NoError(t, err) err = queries.AddDocumentCleanEntry(ctx, &repository.AddDocumentCleanEntryParams{ Cleanid: cleanid, Version: 1, }) - assert.NoError(t, err) + require.NoError(t, err) isextract, err := queries.IsDocumentTextExtracted(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, isextract) - err = queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + textId, err := queries.AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ Version: 1, Bucket: bucket, Key: key, Cleanentryid: cleanid, }) - assert.NoError(t, err) + require.NoError(t, err) + assert.NotNil(t, textId) + assert.NotEqual(t, pgtype.UUID{}, textId) isextract, err = queries.IsDocumentTextExtracted(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, isextract) text, err := queries.GetTextEntryByDocId(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, text.Documentid) assert.Equal(t, bucket, text.Bucket) assert.Equal(t, key, text.Key) assert.Equal(t, int64(1), text.Version) - assert.NotEqual(t, pgtype.UUID{}, text.ID) - assert.True(t, text.ID.Valid) + assert.Equal(t, textId, text.ID) } diff --git a/internal/document/clean/clean.go b/internal/document/clean/clean.go index 2155b579..c84afe47 100644 --- a/internal/document/clean/clean.go +++ b/internal/document/clean/clean.go @@ -90,7 +90,7 @@ func (s *Service) clean(ctx context.Context, id uuid.UUID) error { slog.Debug("cleaning document", "id", id.String()) docId := database.MustToDBUUID(id) - doc, err := s.cfg.GetDBQueries().GetDocument(ctx, docId) + doc, err := s.cfg.GetDBQueries().GetDocumentSummary(ctx, docId) if err != nil { return err } diff --git a/internal/document/clean/clean_test.go b/internal/document/clean/clean_test.go index a251876c..d8ee7629 100644 --- a/internal/document/clean/clean_test.go +++ b/internal/document/clean/clean_test.go @@ -35,7 +35,7 @@ func TestClean(t *testing.T) { cfg: cfg, } - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: uuid.New(), Hash: "example_hash", @@ -46,7 +46,7 @@ func TestClean(t *testing.T) { } dbid := database.MustToDBUUID(doc.ID) - pool.ExpectQuery("name: GetDocument :one").WithArgs(dbid). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(dbid). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(dbid, database.MustToDBUUID(doc.ClientID), doc.Hash), @@ -103,7 +103,7 @@ func TestClean(t *testing.T) { }, nil) err = svc.clean(ctx, doc.ID) - assert.NoError(t, err) + require.NoError(t, err) } func TestExecuteCleanTasks(t *testing.T) { @@ -154,7 +154,7 @@ func TestExecuteCleanTasks(t *testing.T) { Hash: hash, Location: inloc, }) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, ExecuteCleanResponse{ location: &inloc, }, *outloc) @@ -173,7 +173,7 @@ func TestStoreClean(t *testing.T) { cfg: cfg, } - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), } inloc := document.Location{ @@ -208,7 +208,7 @@ func TestStoreClean(t *testing.T) { pool.ExpectCommit() err = svc.storeClean(ctx, doc.ID, params) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("diff prev entry", func(t *testing.T) { mimeType := "application/pdf" @@ -239,7 +239,7 @@ func TestStoreClean(t *testing.T) { pool.ExpectCommit() err = svc.storeClean(ctx, doc.ID, params) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("same fail", func(t *testing.T) { reason := InvalidDocumentMimeType diff --git a/internal/document/clean/contentType_test.go b/internal/document/clean/contentType_test.go index 06642235..8388e0a8 100644 --- a/internal/document/clean/contentType_test.go +++ b/internal/document/clean/contentType_test.go @@ -13,6 +13,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestGetBodyMimeType(t *testing.T) { @@ -48,7 +49,7 @@ func TestGetBodyMimeType(t *testing.T) { }, nil) contentType, err := svc.getBodyMimeType(ctx, params, int64(len(bodyStr))) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, MimeTypeInvalid, contentType) }) t.Run("pdf", func(t *testing.T) { @@ -94,7 +95,7 @@ func TestGetBodyMimeType(t *testing.T) { }, nil) contentType, err := svc.getBodyMimeType(ctx, params, int64(len(bodyStr))) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, MimeTypePDF, contentType) }) t.Run("pdf start", func(t *testing.T) { @@ -140,7 +141,7 @@ func TestGetBodyMimeType(t *testing.T) { }, nil) contentType, err := svc.getBodyMimeType(ctx, params, int64(len(bodyStr))) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, MimeTypeInvalid, contentType) }) t.Run("pdf end", func(t *testing.T) { @@ -186,7 +187,7 @@ func TestGetBodyMimeType(t *testing.T) { }, nil) contentType, err := svc.getBodyMimeType(ctx, params, int64(len(bodyStr))) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, MimeTypeInvalid, contentType) }) t.Run("short", func(t *testing.T) { @@ -281,7 +282,7 @@ func TestGetAcceptedMimeType(t *testing.T) { inType := "invalid_type" contentType, err := svc.getAcceptedMimeType(ctx, params, &inType, int64(len(bodyStr))) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, MimeTypeInvalid, contentType) }) t.Run("pdf mimetype", func(t *testing.T) { @@ -294,7 +295,7 @@ func TestGetAcceptedMimeType(t *testing.T) { } inType := "application/pdf" contentType, err := svc.getAcceptedMimeType(ctx, &CleanParams{}, &inType, 0) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, MimeTypePDF, contentType) }) t.Run("pdf format", func(t *testing.T) { @@ -340,7 +341,7 @@ func TestGetAcceptedMimeType(t *testing.T) { inType := "invalid_type" contentType, err := svc.getAcceptedMimeType(ctx, params, &inType, int64(len(bodyStr))) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, MimeTypePDF, contentType) }) } @@ -380,7 +381,7 @@ func TestGetBytesBuffer(t *testing.T) { }, nil) buffer, err := svc.getBytesBuffer(ctx, params, start, length) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, buffer) }) t.Run("negative start", func(t *testing.T) { @@ -417,7 +418,7 @@ func TestGetBytesBuffer(t *testing.T) { }, nil) buffer, err := svc.getBytesBuffer(ctx, params, start, length) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, buffer) }) t.Run("zero length", func(t *testing.T) { diff --git a/internal/document/clean/content_test.go b/internal/document/clean/content_test.go index b4243544..9a54148d 100644 --- a/internal/document/clean/content_test.go +++ b/internal/document/clean/content_test.go @@ -12,6 +12,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestGetContent(t *testing.T) { @@ -50,7 +51,7 @@ func TestGetContent(t *testing.T) { }, nil) content, err := svc.getContent(ctx, params, mimeType) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, content) }) } diff --git a/internal/document/clean/create_test.go b/internal/document/clean/create_test.go index a459c13d..2b68efd5 100644 --- a/internal/document/clean/create_test.go +++ b/internal/document/clean/create_test.go @@ -20,7 +20,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/google/uuid" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) @@ -50,7 +49,7 @@ func TestCreate(t *testing.T) { cfg: cfg, } - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: uuid.New(), Hash: "example_hash", @@ -65,7 +64,7 @@ func TestCreate(t *testing.T) { pgxmock.NewRows([]string{"isclean"}). AddRow(false), ) - pool.ExpectQuery("name: GetDocument :one").WithArgs(dbid). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(dbid). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(dbid, database.MustToDBUUID(doc.ClientID), doc.Hash), @@ -130,7 +129,7 @@ func TestCreate(t *testing.T) { }, nil) err = svc.Clean(ctx, doc.ID) - assert.NoError(t, err) + require.NoError(t, err) } func TestInformClean(t *testing.T) { @@ -156,5 +155,5 @@ func TestInformClean(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err := svc.informClean(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/document/clean/pdf_test.go b/internal/document/clean/pdf_test.go index 5ec9e376..b45c214d 100644 --- a/internal/document/clean/pdf_test.go +++ b/internal/document/clean/pdf_test.go @@ -9,6 +9,7 @@ import ( "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIsValidDPI(t *testing.T) { @@ -17,9 +18,9 @@ func TestIsValidDPI(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfHelloWorld)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) err = pdfCtx.EnsurePageCount() - assert.NoError(t, err) + require.NoError(t, err) dims := types.Dim{ Width: TEXTRACT_MIN_DIMENSION, Height: TEXTRACT_MIN_DIMENSION, @@ -27,7 +28,7 @@ func TestIsValidDPI(t *testing.T) { boxes, err := pdfCtx.PageBoundaries(types.IntSet{ 1: true, }) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidDPI(boxes[0].MediaBox(), dims) assert.Nil(t, reason) @@ -37,9 +38,9 @@ func TestIsValidDPI(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfWithImg)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) err = pdfCtx.EnsurePageCount() - assert.NoError(t, err) + require.NoError(t, err) dims := types.Dim{ Width: TEXTRACT_MIN_DIMENSION, Height: TEXTRACT_MIN_DIMENSION, @@ -47,7 +48,7 @@ func TestIsValidDPI(t *testing.T) { boxes, err := pdfCtx.PageBoundaries(types.IntSet{ 1: true, }) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidDPI(boxes[0].MediaBox(), dims) assert.Nil(t, reason) @@ -57,9 +58,9 @@ func TestIsValidDPI(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfWithImg)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) err = pdfCtx.EnsurePageCount() - assert.NoError(t, err) + require.NoError(t, err) dims := types.Dim{ Width: math.MaxFloat64, Height: math.MaxFloat64, @@ -67,7 +68,7 @@ func TestIsValidDPI(t *testing.T) { boxes, err := pdfCtx.PageBoundaries(types.IntSet{ 1: true, }) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidDPI(boxes[0].MediaBox(), dims) assert.Equal(t, InvalidDocumentSmallDPI, *reason) @@ -77,9 +78,9 @@ func TestIsValidDPI(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfWithImg)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) err = pdfCtx.EnsurePageCount() - assert.NoError(t, err) + require.NoError(t, err) dims := types.Dim{ Width: math.MaxFloat64, Height: 1, @@ -87,7 +88,7 @@ func TestIsValidDPI(t *testing.T) { boxes, err := pdfCtx.PageBoundaries(types.IntSet{ 1: true, }) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidDPI(boxes[0].MediaBox(), dims) assert.Equal(t, InvalidDocumentSmallDPI, *reason) @@ -97,9 +98,9 @@ func TestIsValidDPI(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfWithImg)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) err = pdfCtx.EnsurePageCount() - assert.NoError(t, err) + require.NoError(t, err) dims := types.Dim{ Width: 1, Height: math.MaxFloat64, @@ -107,7 +108,7 @@ func TestIsValidDPI(t *testing.T) { boxes, err := pdfCtx.PageBoundaries(types.IntSet{ 1: true, }) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidDPI(boxes[0].MediaBox(), dims) assert.Equal(t, InvalidDocumentSmallDPI, *reason) @@ -117,9 +118,9 @@ func TestIsValidDPI(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfWithImg)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) err = pdfCtx.EnsurePageCount() - assert.NoError(t, err) + require.NoError(t, err) dims := types.Dim{ Width: 1, Height: 1, @@ -127,7 +128,7 @@ func TestIsValidDPI(t *testing.T) { boxes, err := pdfCtx.PageBoundaries(types.IntSet{ 1: true, }) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidDPI(boxes[0].MediaBox(), dims) assert.Nil(t, reason) @@ -140,7 +141,7 @@ func TestIsValidDimensions(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfHelloWorld)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidDimensions(pdfCtx) assert.Nil(t, reason) @@ -150,7 +151,7 @@ func TestIsValidDimensions(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfHelloWorld)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) pdf.maxDimension = 1 @@ -162,7 +163,7 @@ func TestIsValidDimensions(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfHelloWorld)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) pdf.minDimension = TEXTRACT_MAX_DIMENSION @@ -177,7 +178,7 @@ func TestIsValidPageCount(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfHelloWorld)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) reason := pdf.isValidPageCount(pdfCtx) assert.Nil(t, reason) @@ -187,7 +188,7 @@ func TestIsValidPageCount(t *testing.T) { pdf := NewPDF(strings.NewReader(pdfTwoPages)) pdfCtx, err := pdfcpu.ReadWithContext(ctx, pdf.pdf, pdf.config) - assert.NoError(t, err) + require.NoError(t, err) pdf.maxPages = 1 diff --git a/internal/document/get.go b/internal/document/get.go index 02566fa7..05deff9e 100644 --- a/internal/document/get.go +++ b/internal/document/get.go @@ -2,21 +2,42 @@ package document import ( "context" + "encoding/json" "queryorchestration/internal/database" "github.com/google/uuid" ) -func (s *Service) Get(ctx context.Context, id uuid.UUID) (*Document, error) { - doc, err := s.cfg.GetDBQueries().GetDocument(ctx, database.MustToDBUUID(id)) +func (s *Service) GetSummary(ctx context.Context, id uuid.UUID) (*DocumentSummary, error) { + doc, err := s.cfg.GetDBQueries().GetDocumentSummary(ctx, database.MustToDBUUID(id)) if err != nil { return nil, err } - return &Document{ + return &DocumentSummary{ ID: database.MustToUUID(doc.ID), ClientID: database.MustToUUID(doc.Clientid), Hash: doc.Hash, }, nil } + +func (s *Service) GetExternal(ctx context.Context, id uuid.UUID) (*DocumentExternal, error) { + doc, err := s.cfg.GetDBQueries().GetDocumentExternal(ctx, database.MustToDBUUID(id)) + if err != nil { + return nil, err + } + + var fields map[string]interface{} + err = json.Unmarshal(doc.Fields, &fields) + if err != nil { + return nil, err + } + + return &DocumentExternal{ + Id: database.MustToUUID(doc.ID), + ClientID: doc.Clientid, + Hash: doc.Hash, + Fields: fields, + }, nil +} diff --git a/internal/document/get_test.go b/internal/document/get_test.go index 04dbada6..3c737c4d 100644 --- a/internal/document/get_test.go +++ b/internal/document/get_test.go @@ -16,7 +16,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestGet(t *testing.T) { +func TestGetSummary(t *testing.T) { ctx := context.Background() pool, err := pgxmock.NewPool() @@ -27,19 +27,50 @@ func TestGet(t *testing.T) { svc := document.New(cfg) - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: uuid.New(), Hash: "example_hash", } - pool.ExpectQuery("name: GetDocument :one").WithArgs(database.MustToDBUUID(doc.ID)). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(database.MustToDBUUID(doc.ID)). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(database.MustToDBUUID(doc.ID), database.MustToDBUUID(doc.ClientID), doc.Hash), ) - adoc, err := svc.Get(ctx, doc.ID) - assert.NoError(t, err) + adoc, err := svc.GetSummary(ctx, doc.ID) + require.NoError(t, err) + assert.Equal(t, &doc, adoc) +} + +func TestGetExternal(t *testing.T) { + ctx := context.Background() + + pool, err := pgxmock.NewPool() + require.NoError(t, err) + cfg := &serviceconfig.BaseConfig{} + cfg.DBPool = pool + cfg.DBQueries = repository.New(pool) + + svc := document.New(cfg) + + doc := document.DocumentExternal{ + Id: uuid.New(), + ClientID: "externalID", + Hash: "example", + Fields: map[string]interface{}{ + "json": "hello", + }, + } + + pool.ExpectQuery("name: GetDocumentExternal :one").WithArgs(database.MustToDBUUID(doc.Id)). + WillReturnRows( + pgxmock.NewRows([]string{"id", "clientId", "hash", "fields"}). + AddRow(database.MustToDBUUID(doc.Id), "externalID", "example", []byte(`{"json": "hello"}`)), + ) + + adoc, err := svc.GetExternal(ctx, doc.Id) + require.NoError(t, err) assert.Equal(t, &doc, adoc) } diff --git a/internal/document/init/create_test.go b/internal/document/init/create_test.go index dccf49bc..02d4175a 100644 --- a/internal/document/init/create_test.go +++ b/internal/document/init/create_test.go @@ -35,7 +35,7 @@ func TestCreate(t *testing.T) { svc := New(cfg) clientId := uuid.New() - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: clientId, Hash: "example_hash", @@ -57,7 +57,7 @@ func TestCreate(t *testing.T) { pool.ExpectExec("name: AddDocumentEntry :exec").WithArgs(database.MustToDBUUID(doc.ID), location.Bucket, location.Key). WillReturnResult(pgxmock.NewResult("", 1)) pool.ExpectCommit() - pool.ExpectQuery("name: GetDocument :one").WithArgs(database.MustToDBUUID(doc.ID)). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(database.MustToDBUUID(doc.ID)). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(database.MustToDBUUID(doc.ID), database.MustToDBUUID(doc.ClientID), doc.Hash), @@ -86,7 +86,7 @@ func TestCreate(t *testing.T) { Location: location, Hash: doc.Hash, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, doc.ID, id) } @@ -101,7 +101,7 @@ func TestGetCreateParams(t *testing.T) { svc := New(cfg) - doc := document.Document{ + doc := document.DocumentSummary{ ClientID: uuid.New(), Hash: "example_hash", } @@ -119,7 +119,7 @@ func TestGetCreateParams(t *testing.T) { Location: location, Hash: doc.Hash, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, &createDocumentParams{ ClientID: database.MustToDBUUID(doc.ClientID), Hash: doc.Hash, @@ -138,7 +138,7 @@ func TestGetCreateParamsExisting(t *testing.T) { svc := New(cfg) - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: uuid.New(), Hash: "example_hash", @@ -158,7 +158,7 @@ func TestGetCreateParamsExisting(t *testing.T) { Location: location, Hash: doc.Hash, }) - assert.NoError(t, err) + require.NoError(t, err) dbid := database.MustToDBUUID(doc.ID) assert.Equal(t, &createDocumentParams{ ID: &dbid, @@ -179,7 +179,7 @@ func TestGetCreateParamsCurrentDocErr(t *testing.T) { svc := New(cfg) - doc := document.Document{ + doc := document.DocumentSummary{ ClientID: uuid.New(), Hash: "example_hash", } @@ -209,7 +209,7 @@ func TestSubmitCreate(t *testing.T) { svc := New(cfg) - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: uuid.New(), Hash: "example_hash", @@ -234,7 +234,7 @@ func TestSubmitCreate(t *testing.T) { Location: location, Hash: doc.Hash, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, doc.ID, id) } @@ -249,7 +249,7 @@ func TestSubmitCreateExists(t *testing.T) { svc := New(cfg) - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: uuid.New(), Hash: "example_hash", @@ -271,7 +271,7 @@ func TestSubmitCreateExists(t *testing.T) { Location: location, Hash: doc.Hash, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, doc.ID, id) } @@ -292,10 +292,10 @@ func TestGetClientIDFromKey(t *testing.T) { assert.Error(t, err) aid, err := svc.GetClientIDFromKey(fmt.Sprintf("%s/%s/bbb", id.String(), uuid.NewString())) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, aid) aid, err = svc.GetClientIDFromKey(fmt.Sprintf("%s/bbb", id.String())) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, aid) } diff --git a/internal/document/list.go b/internal/document/list.go index 6855d2c6..18969b73 100644 --- a/internal/document/list.go +++ b/internal/document/list.go @@ -4,28 +4,19 @@ import ( "context" "queryorchestration/internal/database" - - "github.com/google/uuid" ) -type DocumentInList struct { - ID uuid.UUID - Bucket string - Key string -} - -func (s *Service) ListByClientExternalId(ctx context.Context, id string) ([]*DocumentInList, error) { +func (s *Service) ListByClientExternalId(ctx context.Context, id string) ([]*DocumentSummary, error) { documents, err := s.cfg.GetDBQueries().ListDocumentsByClientExternalId(ctx, id) if err != nil { return nil, err } - docs := make([]*DocumentInList, len(documents)) + docs := make([]*DocumentSummary, len(documents)) for i, doc := range documents { - docs[i] = &DocumentInList{ - ID: database.MustToUUID(doc.ID), - Bucket: doc.Bucket, - Key: doc.Key, + docs[i] = &DocumentSummary{ + ID: database.MustToUUID(doc.ID), + Hash: doc.Hash, } } diff --git a/internal/document/list_test.go b/internal/document/list_test.go index 7eceef16..41f90cd1 100644 --- a/internal/document/list_test.go +++ b/internal/document/list_test.go @@ -27,21 +27,20 @@ func TestListByClientId(t *testing.T) { svc := document.New(cfg) clientId := "externalId" - doc := []*document.DocumentInList{ + doc := []*document.DocumentSummary{ { - ID: uuid.New(), - Bucket: "bucketone", - Key: "keyone", + ID: uuid.New(), + Hash: "bucketone", }, } pool.ExpectQuery("name: ListDocumentsByClientExternalId :many").WithArgs(clientId). WillReturnRows( - pgxmock.NewRows([]string{"id", "bucket", "key"}). - AddRow(database.MustToDBUUID(doc[0].ID), doc[0].Bucket, doc[0].Key), + pgxmock.NewRows([]string{"id", "hash"}). + AddRow(database.MustToDBUUID(doc[0].ID), doc[0].Hash), ) adoc, err := svc.ListByClientExternalId(ctx, clientId) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, doc, adoc) } diff --git a/internal/document/service.go b/internal/document/service.go index 293e2737..bd1834f5 100644 --- a/internal/document/service.go +++ b/internal/document/service.go @@ -11,12 +11,19 @@ type Location struct { Key string } -type Document struct { +type DocumentSummary struct { ID uuid.UUID ClientID uuid.UUID Hash string } +type DocumentExternal struct { + Id uuid.UUID + ClientID string + Hash string + Fields map[string]interface{} +} + type Service struct { cfg serviceconfig.ConfigProvider } diff --git a/internal/document/sync/sync.go b/internal/document/sync/sync.go index d32da877..48ac9899 100644 --- a/internal/document/sync/sync.go +++ b/internal/document/sync/sync.go @@ -11,7 +11,7 @@ import ( ) func (s *Service) Sync(ctx context.Context, id uuid.UUID) error { - doc, err := s.svc.Document.Get(ctx, id) + doc, err := s.svc.Document.GetSummary(ctx, id) if err != nil { return err } diff --git a/internal/document/sync/sync_test.go b/internal/document/sync/sync_test.go index dd73beba..77597d57 100644 --- a/internal/document/sync/sync_test.go +++ b/internal/document/sync/sync_test.go @@ -17,7 +17,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/google/uuid" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -42,13 +41,13 @@ func TestSync(t *testing.T) { ID: uuid.New(), CanSync: true, } - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), ClientID: j.ID, Hash: "example_hash", } - pool.ExpectQuery("name: GetDocument :one").WithArgs(database.MustToDBUUID(doc.ID)). + pool.ExpectQuery("name: GetDocumentSummary :one").WithArgs(database.MustToDBUUID(doc.ID)). WillReturnRows( pgxmock.NewRows([]string{"id", "clientId", "hash"}). AddRow(database.MustToDBUUID(doc.ID), database.MustToDBUUID(doc.ClientID), doc.Hash), @@ -69,5 +68,5 @@ func TestSync(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.Sync(ctx, doc.ID) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/document/text/create_test.go b/internal/document/text/create_test.go index 694efc6e..5ed0890d 100644 --- a/internal/document/text/create_test.go +++ b/internal/document/text/create_test.go @@ -17,7 +17,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/google/uuid" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -68,8 +67,11 @@ func TestCreate(t *testing.T) { pgxmock.NewRows([]string{"id", "documentId", "bucket", "key", "version", "mimetype", "fail"}). AddRow(cleanId, database.MustToDBUUID(id), &inloc.Bucket, &inloc.Key, int32(1), dbmimetype, repository.NullCleanfailtype{}), ) - pool.ExpectExec("name: AddDocumentTextEntry :exec").WithArgs(pgxmock.AnyArg(), inloc.Bucket, inloc.Key, cleanId). - WillReturnResult(pgxmock.NewResult("", 1)) + pool.ExpectQuery("name: AddDocumentTextEntry :one").WithArgs(pgxmock.AnyArg(), inloc.Bucket, inloc.Key, cleanId). + WillReturnRows( + pgxmock.NewRows([]string{"id"}). + AddRow(database.MustToDBUUID(uuid.New())), + ) mockSQS.EXPECT(). SendMessage( @@ -82,7 +84,7 @@ func TestCreate(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.Extract(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("invalid clean", func(t *testing.T) { id := uuid.New() @@ -100,7 +102,7 @@ func TestCreate(t *testing.T) { ) err = svc.Extract(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -127,5 +129,5 @@ func TestInformClean(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err := svc.informExtraction(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/document/text/extract.go b/internal/document/text/extract.go index bf4eea6a..724ace95 100644 --- a/internal/document/text/extract.go +++ b/internal/document/text/extract.go @@ -34,7 +34,7 @@ func (s *Service) extract(ctx context.Context, cleanId uuid.UUID) error { version := build.GetVersionUnixTimestamp() - err = s.cfg.GetDBQueries().AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ + _, err = s.cfg.GetDBQueries().AddDocumentTextEntry(ctx, &repository.AddDocumentTextEntryParams{ Version: version, Bucket: outLocation.Bucket, Key: outLocation.Key, diff --git a/internal/document/text/extract_test.go b/internal/document/text/extract_test.go index 0b8536ce..444a209e 100644 --- a/internal/document/text/extract_test.go +++ b/internal/document/text/extract_test.go @@ -46,11 +46,14 @@ func TestExtract(t *testing.T) { pgxmock.NewRows([]string{"id", "documentId", "bucket", "key", "version", "mimetype", "fail"}). AddRow(dbCleanId, database.MustToDBUUID(id), &inloc.Bucket, &inloc.Key, int64(1), dbmimetype, repository.NullCleanfailtype{}), ) - pool.ExpectExec("name: AddDocumentTextEntry :exec").WithArgs(pgxmock.AnyArg(), inloc.Bucket, inloc.Key, dbCleanId). - WillReturnResult(pgxmock.NewResult("", 1)) + pool.ExpectQuery("name: AddDocumentTextEntry :one").WithArgs(pgxmock.AnyArg(), inloc.Bucket, inloc.Key, dbCleanId). + WillReturnRows( + pgxmock.NewRows([]string{"id"}). + AddRow(database.MustToDBUUID(uuid.New())), + ) err = svc.extract(ctx, cleanId) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("fail clean", func(t *testing.T) { id := uuid.New() @@ -99,6 +102,6 @@ func TestExecuteExtraction(t *testing.T) { ) outloc, err := svc.executeExtraction(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, location, *outloc) } diff --git a/internal/query/create_test.go b/internal/query/create_test.go index f8d7ce9a..ca42a242 100644 --- a/internal/query/create_test.go +++ b/internal/query/create_test.go @@ -45,7 +45,7 @@ func TestCreate(t *testing.T) { } dbType, err := resultprocessor.ToDBQueryType(create.Type) - assert.NoError(t, err) + require.NoError(t, err) pool.ExpectQuery("name: AllQueriesExist :one").WithArgs(database.MustToDBUUIDArray(*create.RequiredQueryIDs)).WillReturnRows( pgxmock.NewRows([]string{"all_exist"}).AddRow(true), @@ -71,7 +71,7 @@ func TestCreate(t *testing.T) { pool.ExpectCommit() id, err := svc.Create(ctx, create) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, q.ID, id) } @@ -94,7 +94,7 @@ func TestCreateMinimal(t *testing.T) { } dbType, err := resultprocessor.ToDBQueryType(create.Type) - assert.NoError(t, err) + require.NoError(t, err) pool.ExpectBeginTx(pgx.TxOptions{}) pool.ExpectQuery("name: CreateQuery :one").WithArgs(dbType).WillReturnRows( @@ -110,7 +110,7 @@ func TestCreateMinimal(t *testing.T) { pool.ExpectCommit() id, err := svc.Create(ctx, create) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, q.ID, id) } @@ -131,7 +131,7 @@ func TestCreateRollback(t *testing.T) { } dbType, err := resultprocessor.ToDBQueryType(create.Type) - assert.NoError(t, err) + require.NoError(t, err) pool.ExpectBeginTx(pgx.TxOptions{}) msg := "database failure" diff --git a/internal/query/createprivate_test.go b/internal/query/createprivate_test.go index b1b68bfa..a764f9ea 100644 --- a/internal/query/createprivate_test.go +++ b/internal/query/createprivate_test.go @@ -26,12 +26,12 @@ func TestGetCreator(t *testing.T) { queryType := resultprocessor.Type(resultprocessor.TypeContextFull) creator, err := svc.getCreator(queryType) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, creator) queryType = resultprocessor.Type(resultprocessor.TypeJsonExtractor) creator, err = svc.getCreator(queryType) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, creator) queryType = resultprocessor.Type(-1) @@ -50,7 +50,7 @@ func TestParseCreateQuery(t *testing.T) { } resultQuery, err := parseCreateQuery(cQuery) - assert.NoError(t, err) + require.NoError(t, err) rQIDs := database.MustToDBUUIDArray(*cQuery.RequiredQueryIDs) qcfg := []byte(*cQuery.Config) assert.EqualExportedValues(t, createQuery{ @@ -100,7 +100,7 @@ func TestSubmitCreate(t *testing.T) { } dbType, err := resultprocessor.ToDBQueryType(create.Type) - assert.NoError(t, err) + require.NoError(t, err) pool.ExpectBeginTx(pgx.TxOptions{}) pool.ExpectQuery("name: CreateQuery :one").WithArgs(dbType).WillReturnRows( @@ -122,7 +122,7 @@ func TestSubmitCreate(t *testing.T) { pool.ExpectCommit() id, err := svc.submitCreate(ctx, create) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, q.ID, id) } @@ -145,7 +145,7 @@ func TestSubmitCreateNoReqsOrConfig(t *testing.T) { } dbType, err := resultprocessor.ToDBQueryType(create.Type) - assert.NoError(t, err) + require.NoError(t, err) pool.ExpectBeginTx(pgx.TxOptions{}) pool.ExpectQuery("name: CreateQuery :one").WithArgs(dbType).WillReturnRows( @@ -161,7 +161,7 @@ func TestSubmitCreateNoReqsOrConfig(t *testing.T) { pool.ExpectCommit() id, err := svc.submitCreate(ctx, create) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, q.ID, id) } @@ -189,7 +189,7 @@ func TestNormalizeCreate(t *testing.T) { ) err = svc.normalizeCreate(ctx, create) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, resultprocessor.Create{ Type: resultprocessor.TypeContextFull, Config: nil, diff --git a/internal/query/get_test.go b/internal/query/get_test.go index 3d6bcfed..cfdc663e 100644 --- a/internal/query/get_test.go +++ b/internal/query/get_test.go @@ -46,7 +46,7 @@ func TestGet(t *testing.T) { ) returnQuery, err := svc.Get(ctx, query.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, query, *returnQuery) } @@ -83,7 +83,7 @@ func TestGetWithVersion(t *testing.T) { ) returnQuery, err := svc.GetWithVersion(ctx, query.ID, version) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, query, *returnQuery) } diff --git a/internal/query/list_test.go b/internal/query/list_test.go index dca8880f..b9a5b0d1 100644 --- a/internal/query/list_test.go +++ b/internal/query/list_test.go @@ -48,7 +48,7 @@ func TestList(t *testing.T) { ) resList, err := svc.List(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, []*query.Query{q}, resList) } @@ -83,7 +83,7 @@ func TestListById(t *testing.T) { ) resList, err := svc.ListById(ctx, []uuid.UUID{q.ID}) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, []*query.Query{q}, resList) } diff --git a/internal/query/normalize_test.go b/internal/query/normalize_test.go index afd520ae..d2ec9c80 100644 --- a/internal/query/normalize_test.go +++ b/internal/query/normalize_test.go @@ -20,43 +20,43 @@ func TestNormalizeConfig(t *testing.T) { s := Service{} err := s.NormalizeConfig(nil) - assert.NoError(t, err) + require.NoError(t, err) entity := resultprocessor.Create{} entity.Config = nil err = s.NormalizeConfig(&entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, entity.Config) cfg := "" entity.Config = &cfg err = s.NormalizeConfig(&entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, entity.Config) cfg = " " entity.Config = &cfg err = s.NormalizeConfig(&entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, entity.Config) cfg = "{}" entity.Config = &cfg err = s.NormalizeConfig(&entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "{}", *(entity.Config)) cfg = "{\"hello\":\"bye\"}" entity.Config = &cfg err = s.NormalizeConfig(&entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "{\"hello\":\"bye\"}", *(entity.Config)) cfg = " { \"hello\" : \"bye\" } " entity.Config = &cfg err = s.NormalizeConfig(&entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "{\"hello\":\"bye\"}", *(entity.Config)) cfg = "{'hello':'bye'}" @@ -81,18 +81,18 @@ func TestNormalizeQueryIDs(t *testing.T) { s := Service{cfg: cfg} err = s.NormalizeQueryIDs(ctx, nil) - assert.NoError(t, err) + require.NoError(t, err) entity := resultprocessor.Create{} entity.RequiredQueryIDs = nil err = s.NormalizeQueryIDs(ctx, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, entity.RequiredQueryIDs) entity.RequiredQueryIDs = &[]uuid.UUID{} err = s.NormalizeQueryIDs(ctx, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, entity.RequiredQueryIDs) ids := []uuid.UUID{uuid.New()} @@ -105,7 +105,7 @@ func TestNormalizeQueryIDs(t *testing.T) { ) err = s.NormalizeQueryIDs(ctx, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, ids, *entity.RequiredQueryIDs) pool.ExpectQuery("name: AllQueriesExist :one").WithArgs(dbids).WillReturnRows( @@ -135,7 +135,7 @@ func TestNormalizeQueryIDs(t *testing.T) { ) err = s.NormalizeQueryIDs(ctx, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, outids, *entity.RequiredQueryIDs) } @@ -160,7 +160,7 @@ func TestNormalizeActiveVersion(t *testing.T) { LatestVersion: 4, } err := s.NormalizeActiveVersion(¤t, nil) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("no update", func(t *testing.T) { @@ -170,7 +170,7 @@ func TestNormalizeActiveVersion(t *testing.T) { } entity := resultprocessor.Update{} err := s.NormalizeActiveVersion(¤t, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, entity.ActiveVersion) }) @@ -184,7 +184,7 @@ func TestNormalizeActiveVersion(t *testing.T) { ActiveVersion: &version, } err := s.NormalizeActiveVersion(¤t, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, entity.ActiveVersion) }) @@ -198,7 +198,7 @@ func TestNormalizeActiveVersion(t *testing.T) { ActiveVersion: &version, } err := s.NormalizeActiveVersion(¤t, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, version, *entity.ActiveVersion) }) @@ -212,7 +212,7 @@ func TestNormalizeActiveVersion(t *testing.T) { ActiveVersion: &version, } err := s.NormalizeActiveVersion(¤t, &entity) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, version, *entity.ActiveVersion) }) diff --git a/internal/query/parse_test.go b/internal/query/parse_test.go index 05a82861..4be21671 100644 --- a/internal/query/parse_test.go +++ b/internal/query/parse_test.go @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseQuery(t *testing.T) { @@ -49,7 +50,7 @@ func TestParseFullActiveQuery(t *testing.T) { } out, err := query.ParseFullActiveQuery(q) - assert.NoError(t, err) + require.NoError(t, err) bcfg := string(q.Config) assert.EqualExportedValues(t, query.Query{ ID: database.MustToUUID(q.ID), @@ -72,7 +73,7 @@ func TestFullActiveQueryEmpty(t *testing.T) { } out, err := query.ParseFullActiveQuery(dbQuery) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, query.Query{ ID: database.MustToUUID(dbQuery.ID), Type: resultprocessor.TypeContextFull, @@ -90,7 +91,7 @@ func TestFullActiveQueryWithNullUUID(t *testing.T) { } out, err := query.ParseFullActiveQuery(dbQuery) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, query.Query{ ID: database.MustToUUID(dbQuery.ID), Type: resultprocessor.TypeContextFull, @@ -110,7 +111,7 @@ func TestFullActiveQueryArray(t *testing.T) { } out, err := query.ParseFullActiveQueryArray(dbQueries) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, []*query.Query{ { ID: database.MustToUUID(dbQueries[0].ID), diff --git a/internal/query/result/get_test.go b/internal/query/result/get_test.go index 003843fe..0d6787ae 100644 --- a/internal/query/result/get_test.go +++ b/internal/query/result/get_test.go @@ -21,11 +21,11 @@ func TestGetValueByType(t *testing.T) { _, err := getValueByType(resultprocessor.Type(-1), "example_val") assert.Error(t, err) pro, err := getValueByType(resultprocessor.TypeContextFull, "example_context") - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, pro) assert.Equal(t, "example_context", pro.GetStoreValue()) pro, err = getValueByType(resultprocessor.TypeJsonExtractor, "example_json") - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, pro) assert.Equal(t, "example_json", pro.GetStoreValue()) } @@ -56,7 +56,7 @@ func TestGetValueWithVersion(t *testing.T) { ) val, err := svc.GetValueWithVersion(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) v := jsonextractor.NewResult(value) assert.Equal(t, v, val) assert.Equal(t, value, v.GetStoreValue()) diff --git a/internal/query/result/process_test.go b/internal/query/result/process_test.go index 666b6fd7..295b3f75 100644 --- a/internal/query/result/process_test.go +++ b/internal/query/result/process_test.go @@ -62,7 +62,7 @@ func TestProcess(t *testing.T) { ) val, err := svc.Process(ctx, ¶ms) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, val) assert.Equal(t, "example_value", val.GetStoreValue()) } @@ -81,11 +81,11 @@ func TestListRequiredValue(t *testing.T) { } pr, err := svc.listRequiredValues(ctx, nil, nil) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, pr) pr, err = svc.listRequiredValues(ctx, &Process{}, &resultprocessor.Query{}) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, pr) pr, err = svc.listRequiredValues(ctx, &Process{}, @@ -93,7 +93,7 @@ func TestListRequiredValue(t *testing.T) { RequiredQueryIDs: &[]uuid.UUID{}, }, ) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, pr) query := &resultprocessor.Query{ @@ -116,7 +116,7 @@ func TestListRequiredValue(t *testing.T) { ) pr, err = svc.listRequiredValues(ctx, ¶ms, query) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []resultprocessor.Value{ jsonextractor.NewResult(strVal), }, pr) @@ -126,11 +126,11 @@ func TestGetProcessor(t *testing.T) { svc := Service{} pr, err := svc.getProcessor(resultprocessor.TypeJsonExtractor) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, pr) pr, err = svc.getProcessor(resultprocessor.TypeContextFull) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, pr) _, err = svc.getProcessor(resultprocessor.Type(-1)) @@ -148,7 +148,7 @@ func TestParseQueryRequirementValueArray(t *testing.T) { } out, err := parseQueryRequirementValueArray(in) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []resultprocessor.Value{ jsonextractor.NewResult(exval), }, out) diff --git a/internal/query/result/processor/parse_test.go b/internal/query/result/processor/parse_test.go index 562be2da..880cb8f6 100644 --- a/internal/query/result/processor/parse_test.go +++ b/internal/query/result/processor/parse_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseDBCollectorQuery(t *testing.T) { @@ -21,7 +22,7 @@ func TestParseDBCollectorQuery(t *testing.T) { Queryversion: 1, } value, err := resultprocessor.ParseDBCollectorQuery(&dbResult) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, uuid.Nil, value.ID) assert.Nil(t, value.RequiredQueryIDs) assert.Equal(t, int32(1), value.Version) @@ -35,7 +36,7 @@ func TestParseDBCollectorQuery(t *testing.T) { func TestParseDBNullType(t *testing.T) { qType := repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeJsonExtractor} value, err := resultprocessor.ParseDBNullType(qType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, resultprocessor.Type(resultprocessor.TypeJsonExtractor), value) qType = repository.NullQuerytype{} @@ -50,19 +51,19 @@ func TestParseDBNullType(t *testing.T) { func TestParseDBType(t *testing.T) { qType := repository.QuerytypeJsonExtractor value, err := resultprocessor.ParseDBType(qType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, resultprocessor.Type(resultprocessor.TypeJsonExtractor), value) qType = repository.QuerytypeContextFull value, err = resultprocessor.ParseDBType(qType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, resultprocessor.Type(resultprocessor.TypeContextFull), value) } func TestToDBQueryType(t *testing.T) { dbQueryType := resultprocessor.Type(resultprocessor.TypeJsonExtractor) value, err := resultprocessor.ToDBQueryType(dbQueryType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, repository.Querytype(repository.QuerytypeJsonExtractor), value) dbQueryType = resultprocessor.Type(-1) @@ -71,7 +72,7 @@ func TestToDBQueryType(t *testing.T) { dbQueryType = resultprocessor.Type(resultprocessor.TypeContextFull) value, err = resultprocessor.ToDBQueryType(dbQueryType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, repository.Querytype(repository.QuerytypeContextFull), value) } @@ -81,7 +82,7 @@ func TestToDBQueryTypeArray(t *testing.T) { resultprocessor.TypeContextFull, } value, err := resultprocessor.ToDBQueryTypeArray(inArr) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []repository.Querytype{ repository.QuerytypeJsonExtractor, repository.QuerytypeContextFull, @@ -97,7 +98,7 @@ func TestToDBQueryTypeArray(t *testing.T) { func TestToDBNullQueryType(t *testing.T) { dbQueryType := resultprocessor.Type(resultprocessor.TypeJsonExtractor) value, err := resultprocessor.ToDBNullQueryType(dbQueryType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeJsonExtractor}, value) dbQueryType = resultprocessor.Type(-1) @@ -106,14 +107,14 @@ func TestToDBNullQueryType(t *testing.T) { dbQueryType = resultprocessor.Type(resultprocessor.TypeContextFull) value, err = resultprocessor.ToDBNullQueryType(dbQueryType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeContextFull}, value) } func TestParseFullQuery(t *testing.T) { var q *repository.Fullactivequery out, err := resultprocessor.ParseFullQuery(q) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, out) q = &repository.Fullactivequery{ @@ -124,7 +125,7 @@ func TestParseFullQuery(t *testing.T) { } out, err = resultprocessor.ParseFullQuery(q) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &resultprocessor.Query{ ID: database.MustToUUID(q.ID), Type: resultprocessor.TypeContextFull, @@ -140,7 +141,7 @@ func TestParseFullQuery(t *testing.T) { } out, err = resultprocessor.ParseFullQuery(q) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, &resultprocessor.Query{ ID: database.MustToUUID(q.ID), Type: resultprocessor.TypeContextFull, @@ -159,7 +160,7 @@ func TestParseFullQuery(t *testing.T) { } out, err = resultprocessor.ParseFullQuery(q) - assert.NoError(t, err) + require.NoError(t, err) cfg := "hello" assert.EqualExportedValues(t, &resultprocessor.Query{ ID: database.MustToUUID(q.ID), @@ -173,7 +174,7 @@ func TestParseFullQuery(t *testing.T) { func TestParseFullQueryArray(t *testing.T) { var q []*repository.Fullactivequery out, err := resultprocessor.ParseFullQueryArray(q) - assert.NoError(t, err) + require.NoError(t, err) assert.ElementsMatch(t, []*resultprocessor.Query{}, out) q = []*repository.Fullactivequery{ @@ -186,7 +187,7 @@ func TestParseFullQueryArray(t *testing.T) { } out, err = resultprocessor.ParseFullQueryArray(q) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, []*resultprocessor.Query{ { ID: database.MustToUUID(q[0].ID), diff --git a/internal/query/result/set/set_test.go b/internal/query/result/set/set_test.go index ba421a29..136c4ffa 100644 --- a/internal/query/result/set/set_test.go +++ b/internal/query/result/set/set_test.go @@ -20,7 +20,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/google/uuid" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -122,7 +121,7 @@ func TestSet(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.Set(ctx, ¶ms) - assert.NoError(t, err) + require.NoError(t, err) } func TestInformQueryDependents(t *testing.T) { @@ -186,5 +185,5 @@ func TestInformQueryDependents(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.informQueryDependents(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/query/result/sync/trigger_test.go b/internal/query/result/sync/trigger_test.go index 3b8110c7..184a87ee 100644 --- a/internal/query/result/sync/trigger_test.go +++ b/internal/query/result/sync/trigger_test.go @@ -15,7 +15,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/google/uuid" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -56,7 +55,7 @@ func TestTriggerSync(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.TriggerSync(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) } func TestTriggerMultiSync(t *testing.T) { @@ -102,5 +101,5 @@ func TestTriggerMultiSync(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.TriggerMultiSync(ctx, docId, qIds) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/query/test/test_test.go b/internal/query/test/test_test.go index cbb98ceb..e6376182 100644 --- a/internal/query/test/test_test.go +++ b/internal/query/test/test_test.go @@ -39,7 +39,7 @@ func TestTest(t *testing.T) { }), }) - doc := document.Document{ + doc := document.DocumentSummary{ ID: uuid.New(), } params := &result.Process{ @@ -65,6 +65,6 @@ func TestTest(t *testing.T) { ) result, err := svc.Test(ctx, *params) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "old_value", result) } diff --git a/internal/query/types/contextFull/creator_test.go b/internal/query/types/contextFull/creator_test.go index 7675857a..2dbcd44f 100644 --- a/internal/query/types/contextFull/creator_test.go +++ b/internal/query/types/contextFull/creator_test.go @@ -31,5 +31,5 @@ func TestCreatorValidate(t *testing.T) { } err = svc.Validate(ctx, entity) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/query/types/contextFull/process_test.go b/internal/query/types/contextFull/process_test.go index a1013f36..2c2600db 100644 --- a/internal/query/types/contextFull/process_test.go +++ b/internal/query/types/contextFull/process_test.go @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestContextFull(t *testing.T) { @@ -25,7 +26,7 @@ func TestContextFull(t *testing.T) { values := []resultprocessor.Value{} value, err := extractor.Process(ctx, query, values) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, `{"keyone":"valueone","keytwo":"valuetwo"}`, value) values = []resultprocessor.Value{ diff --git a/internal/query/types/contextFull/updator_test.go b/internal/query/types/contextFull/updator_test.go index 05496ac0..e4721e9a 100644 --- a/internal/query/types/contextFull/updator_test.go +++ b/internal/query/types/contextFull/updator_test.go @@ -39,5 +39,5 @@ func TestUpdatorValidate(t *testing.T) { } err = svc.Validate(ctx, current, entity) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/query/types/jsonExtractor/creator_test.go b/internal/query/types/jsonExtractor/creator_test.go index e2c21abd..3805b50a 100644 --- a/internal/query/types/jsonExtractor/creator_test.go +++ b/internal/query/types/jsonExtractor/creator_test.go @@ -34,5 +34,5 @@ func TestCreatorValidate(t *testing.T) { } err = svc.Validate(ctx, entity) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/query/types/jsonExtractor/process_test.go b/internal/query/types/jsonExtractor/process_test.go index 217ab83d..30fd8915 100644 --- a/internal/query/types/jsonExtractor/process_test.go +++ b/internal/query/types/jsonExtractor/process_test.go @@ -51,7 +51,7 @@ func TestJSONProcess(t *testing.T) { ) value, err := extractor.Process(ctx, query, values) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, entryValue, value) entryValue = "" @@ -66,7 +66,7 @@ func TestJSONProcess(t *testing.T) { ) value, err = extractor.Process(ctx, query, values) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, entryValue, value) entryValue = "1" @@ -81,7 +81,7 @@ func TestJSONProcess(t *testing.T) { ) value, err = extractor.Process(ctx, query, values) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, entryValue, value) } diff --git a/internal/query/types/jsonExtractor/updator_test.go b/internal/query/types/jsonExtractor/updator_test.go index 7e2378f7..a40fba13 100644 --- a/internal/query/types/jsonExtractor/updator_test.go +++ b/internal/query/types/jsonExtractor/updator_test.go @@ -38,5 +38,5 @@ func TestUpdatorValidate(t *testing.T) { } err = svc.Validate(ctx, current, entity) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/query/update/update_test.go b/internal/query/update/update_test.go index 5935434a..bca3d787 100644 --- a/internal/query/update/update_test.go +++ b/internal/query/update/update_test.go @@ -21,7 +21,6 @@ import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/pashagolub/pgxmock/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -85,5 +84,5 @@ func TestUpdate(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err = svc.Update(ctx, update) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/query/update/updateprivate_test.go b/internal/query/update/updateprivate_test.go index 82ebf6df..1548160f 100644 --- a/internal/query/update/updateprivate_test.go +++ b/internal/query/update/updateprivate_test.go @@ -41,12 +41,12 @@ func TestGetUpdator(t *testing.T) { queryType := resultprocessor.Type(resultprocessor.TypeContextFull) updator, err := svc.getUpdator(queryType) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, updator) queryType = resultprocessor.Type(resultprocessor.TypeJsonExtractor) updator, err = svc.getUpdator(queryType) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, updator) queryType = resultprocessor.Type(-1) @@ -102,7 +102,7 @@ func TestSubmitUpdate(t *testing.T) { pool.ExpectCommit() err = svc.submitUpdate(ctx, &q, update) - assert.NoError(t, err) + require.NoError(t, err) } func TestSubmitUpdateRollback(t *testing.T) { @@ -189,7 +189,7 @@ func TestSubmitUpdateRequiredQueries(t *testing.T) { pool.ExpectCommit() err = svc.submitUpdate(ctx, &q, update) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("all nil", func(t *testing.T) { @@ -228,7 +228,7 @@ func TestSubmitUpdateRequiredQueries(t *testing.T) { pool.ExpectCommit() err = svc.submitUpdate(ctx, &q, update) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -261,7 +261,7 @@ func TestSubmitUpdateActiveVersion(t *testing.T) { pool.ExpectCommit() err = svc.submitUpdate(ctx, &q, update) - assert.NoError(t, err) + require.NoError(t, err) } func TestGetSetDifference(t *testing.T) { @@ -306,7 +306,7 @@ func TestNormalizeUpdate(t *testing.T) { } err = svc.normalizeUpdate(ctx, current, update) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, resultprocessor.Update{ ID: current.ID, ActiveVersion: &aV, @@ -418,7 +418,7 @@ func TestNormalizeUpdateRequiredQueryIDs(t *testing.T) { } err = svc.normalizeUpdateRequiredQueryIDs(ctx, current, update) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, resultprocessor.Update{ ID: current.ID, }, *update) @@ -521,7 +521,7 @@ func TestNormalizeUpdateRequiredQueryIDs(t *testing.T) { ) err = svc.normalizeUpdateRequiredQueryIDs(ctx, current, update) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, resultprocessor.Update{ ID: current.ID, }, *update) @@ -546,7 +546,7 @@ func TestInformUpdate(t *testing.T) { } err := svc.informUpdate(ctx, entity) - assert.NoError(t, err) + require.NoError(t, err) }) t.Run("update active version", func(t *testing.T) { ctx := context.Background() @@ -576,6 +576,6 @@ func TestInformUpdate(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err := svc.informUpdate(ctx, entity) - assert.NoError(t, err) + require.NoError(t, err) }) } diff --git a/internal/server/service/listener.go b/internal/server/api/listener.go similarity index 83% rename from internal/server/service/listener.go rename to internal/server/api/listener.go index fea9d31a..a75cd01d 100644 --- a/internal/server/service/listener.go +++ b/internal/server/api/listener.go @@ -1,4 +1,4 @@ -package service +package api import ( "context" @@ -11,10 +11,12 @@ import ( "queryorchestration/internal/server" "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/openapi3filter" "github.com/labstack/echo-contrib/echoprometheus" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" _ "github.com/lib/pq" + oapimiddleware "github.com/oapi-codegen/echo-middleware" echoSwagger "github.com/swaggo/echo-swagger" ) @@ -109,40 +111,23 @@ func New(ctx context.Context, cfg Config) (*Server, error) { e := echo.New() - // Add Prometheus middleware - e.Use(echoprometheus.NewMiddleware("echo")) // Add the middleware + e.Use(echoprometheus.NewMiddleware("echo")) e.GET("/metrics", echoprometheus.NewHandler()) - // Other middlewares e.Use(getSlogCustomEchoMiddleware(cfg.GetLogger())) e.Use(middleware.Recover()) e.Use(middleware.CORS()) cfg.SetRouter(e) - opnapi, err := cfg.RegisterHandlers() if err != nil { return nil, err } - jsonFunc, err := getSwaggerJSONFunc(opnapi) + err = setOapi(e, opnapi) if err != nil { return nil, err } - e.GET("/swagger/doc.json", jsonFunc) - - yamlFunc, err := getSwaggerYAMLFunc(opnapi) - if err != nil { - return nil, err - } - e.GET("/swagger/doc.yaml", yamlFunc) - - e.GET("/swagger/*", echoSwagger.EchoWrapHandler( - echoSwagger.DocExpansion("full"), - echoSwagger.DeepLinking(true), - echoSwagger.DomID("swagger-ui"), - echoSwagger.PersistAuthorization(true), - )) host := "0.0.0.0" port := 8080 @@ -157,6 +142,42 @@ func New(ctx context.Context, cfg Config) (*Server, error) { }, nil } +func setOapi(e *echo.Echo, opnapi *openapi3.T) error { + opnapi.Servers = nil + validatorOptions := &oapimiddleware.Options{ + Skipper: func(c echo.Context) bool { + return len(c.Path()) >= 8 && (c.Path()[:8] == "/swagger" || + c.Path()[:8] == "/metrics") + }, + Options: openapi3filter.Options{ + AuthenticationFunc: openapi3filter.NoopAuthenticationFunc, + MultiError: true, + }, + } + e.Use(oapimiddleware.OapiRequestValidatorWithOptions(opnapi, validatorOptions)) + + jsonFunc, err := getSwaggerJSONFunc(opnapi) + if err != nil { + return err + } + e.GET("/swagger/doc.json", jsonFunc) + + yamlFunc, err := getSwaggerYAMLFunc(opnapi) + if err != nil { + return err + } + e.GET("/swagger/doc.yaml", yamlFunc) + + e.GET("/swagger/*", echoSwagger.EchoWrapHandler( + echoSwagger.DocExpansion("full"), + echoSwagger.DeepLinking(true), + echoSwagger.DomID("swagger-ui"), + echoSwagger.PersistAuthorization(true), + )) + + return nil +} + func (s *Server) Listen() { slog.Info("Listening for requests", "port", s.port) defer func() { diff --git a/internal/server/service/listener_test.go b/internal/server/api/listener_test.go similarity index 96% rename from internal/server/service/listener_test.go rename to internal/server/api/listener_test.go index 240ee8be..b76493d3 100644 --- a/internal/server/service/listener_test.go +++ b/internal/server/api/listener_test.go @@ -1,4 +1,4 @@ -package service +package api import ( "context" @@ -35,12 +35,12 @@ func TestNew(t *testing.T) { defer cleanup() registerHandlers := func() (*openapi3.T, error) { - return nil, nil + return &openapi3.T{}, nil } cfg.RegisterHandlersFunc = registerHandlers serverInstance, err := New(ctx, cfg) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 8080, serverInstance.port) assert.Equal(t, "0.0.0.0", serverInstance.host) assert.Equal(t, "0.0.0.0:8080", serverInstance.address) @@ -61,7 +61,7 @@ func TestRegisterHandlers(t *testing.T) { return &openapi3.T{}, nil } op, err := c.RegisterHandlers() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, &openapi3.T{}, op) assert.Equal(t, op, c.OpenAPI) } diff --git a/internal/server/service/swagger.go b/internal/server/api/swagger.go similarity index 97% rename from internal/server/service/swagger.go rename to internal/server/api/swagger.go index 5631cf12..871f1425 100644 --- a/internal/server/service/swagger.go +++ b/internal/server/api/swagger.go @@ -1,4 +1,4 @@ -package service +package api import ( "net/http" diff --git a/internal/server/service/swagger_test.go b/internal/server/api/swagger_test.go similarity index 86% rename from internal/server/service/swagger_test.go rename to internal/server/api/swagger_test.go index c41bf0ad..46127d1b 100644 --- a/internal/server/service/swagger_test.go +++ b/internal/server/api/swagger_test.go @@ -1,4 +1,4 @@ -package service +package api import ( "net/http" @@ -6,7 +6,7 @@ import ( "strings" "testing" - queryservice "queryorchestration/api/queryService" + queryapi "queryorchestration/api/queryAPI" "github.com/labstack/echo/v4" "github.com/stretchr/testify/assert" @@ -14,7 +14,7 @@ import ( ) func TestGetSwaggerJSONFunc(t *testing.T) { - openapi, err := queryservice.GetSwagger() + openapi, err := queryapi.GetSwagger() require.NoError(t, err) f, err := getSwaggerJSONFunc(openapi) @@ -31,7 +31,7 @@ func TestGetSwaggerJSONFunc(t *testing.T) { } func TestGetSwaggerYAMLFunc(t *testing.T) { - openapi, err := queryservice.GetSwagger() + openapi, err := queryapi.GetSwagger() require.NoError(t, err) f, err := getSwaggerYAMLFunc(openapi) diff --git a/internal/server/runner/listener_test.go b/internal/server/runner/listener_test.go index 140f9583..ff9c779d 100644 --- a/internal/server/runner/listener_test.go +++ b/internal/server/runner/listener_test.go @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestNew(t *testing.T) { @@ -30,7 +31,7 @@ func TestNew(t *testing.T) { }) defer acleanup() err := cfg.SetQueueClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) _, cleanup := test.CreateDB(t, ctx, &test.CreateDatabaseConfig{ Cfg: cfg, }) @@ -46,7 +47,7 @@ func TestNew(t *testing.T) { t.Setenv("QUEUE_URL", "queueName") srvPtr, err := New(ctx, cfg) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, srvPtr) } @@ -68,7 +69,7 @@ func TestRegisterController(t *testing.T) { return runnermock.NewMockController(t) } err = c.RegisterController() - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, runnermock.NewMockController(t), c.Controller) } @@ -90,7 +91,7 @@ func TestPingQueue(t *testing.T) { Return(&sqs.GetQueueAttributesOutput{}, nil) err := c.PingQueue(ctx) - assert.NoError(t, err) + require.NoError(t, err) } func TestGetQueueURL(t *testing.T) { diff --git a/internal/server/runner/poll_test.go b/internal/server/runner/poll_test.go index 7d87a0be..932bb491 100644 --- a/internal/server/runner/poll_test.go +++ b/internal/server/runner/poll_test.go @@ -10,8 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/aws/aws-sdk-go-v2/service/sqs/types" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestPollMessages(t *testing.T) { @@ -103,7 +103,7 @@ func TestPollMessage(t *testing.T) { Return(&sqs.DeleteMessageOutput{}, nil) err := ser.pollMessage(ctx) - assert.NoError(t, err) + require.NoError(t, err) } func TestProcessMessage(t *testing.T) { @@ -150,5 +150,5 @@ func TestProcessMessage(t *testing.T) { Return(&sqs.DeleteMessageOutput{}, nil) err := ser.processMessage(ctx, msg) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/server/server_test.go b/internal/server/server_test.go index 1afbf346..08e63e97 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -12,6 +12,7 @@ import ( "github.com/go-playground/validator/v10" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNew(t *testing.T) { @@ -30,7 +31,7 @@ func TestNew(t *testing.T) { defer cleanup() clean, err := server.New(ctx, cfg) - assert.NoError(t, err) + require.NoError(t, err) defer func() { if err := clean(); err != nil { // Log cleanup error but don't panic since we're shutting down diff --git a/internal/serviceconfig/database/pool_test.go b/internal/serviceconfig/database/pool_test.go index c82f6233..b299ec8c 100644 --- a/internal/serviceconfig/database/pool_test.go +++ b/internal/serviceconfig/database/pool_test.go @@ -13,6 +13,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestSetDBPool(t *testing.T) { @@ -31,7 +32,7 @@ func TestSetDBPool(t *testing.T) { defer cleanup() err := cfg.SetDBPool(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, cfg.GetDBPool()) } @@ -48,7 +49,7 @@ func TestGetDBPoolConfig(t *testing.T) { cfg.DBUser = "user" cfg.DBSecret = "pass" err = cfg.SetDBPoolConfig() - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, cfg.DBPoolConfig) } diff --git a/internal/serviceconfig/database/transaction_test.go b/internal/serviceconfig/database/transaction_test.go index 4110f000..214afc2d 100644 --- a/internal/serviceconfig/database/transaction_test.go +++ b/internal/serviceconfig/database/transaction_test.go @@ -40,10 +40,10 @@ func TestExecuteTransaction(t *testing.T) { Name: clientName, Externalid: externalId, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, clientID, id) return nil }) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/serviceconfig/objectstore/config_test.go b/internal/serviceconfig/objectstore/config_test.go index c59794eb..d1cbaec5 100644 --- a/internal/serviceconfig/objectstore/config_test.go +++ b/internal/serviceconfig/objectstore/config_test.go @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestGetStoreClient(t *testing.T) { @@ -28,7 +29,7 @@ func TestStoreClient(t *testing.T) { ctx := context.Background() c := objectstore.ObjectStoreConfig{} err := c.SetStoreClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, c.StoreClient) } @@ -51,7 +52,7 @@ func TestPingStoreByName(t *testing.T) { Return(&s3.HeadBucketOutput{}, nil) err := c.PingStoreByName(ctx, name) - assert.NoError(t, err) + require.NoError(t, err) } func TestGetS3Client(t *testing.T) { diff --git a/internal/serviceconfig/observability/prometheus/prometheus.md b/internal/serviceconfig/observability/prometheus/prometheus.md index 724a48e3..549d5f05 100644 --- a/internal/serviceconfig/observability/prometheus/prometheus.md +++ b/internal/serviceconfig/observability/prometheus/prometheus.md @@ -9,7 +9,7 @@ Then you can run your service that exposed the metrics. ## Testing the API service Start the API server on the host like -`PGPORT=5430 go run ./cmd/queryService` +`PGPORT=5430 go run ./cmd/queryAPI` Once started you will be able to see the raw metrics at http://localhost:8080/metrics diff --git a/internal/serviceconfig/queue/clientsync/config.go b/internal/serviceconfig/queue/clientsync/config.go index a8267675..5ec04d58 100644 --- a/internal/serviceconfig/queue/clientsync/config.go +++ b/internal/serviceconfig/queue/clientsync/config.go @@ -1,5 +1,7 @@ package clientsync +const EnvName = "CLIENT_SYNC_URL" + type ClientSyncConfig struct { ClientSyncURL string `env:"CLIENT_SYNC_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/config_test.go b/internal/serviceconfig/queue/config_test.go index 4ef995bb..4c9e653d 100644 --- a/internal/serviceconfig/queue/config_test.go +++ b/internal/serviceconfig/queue/config_test.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestGetQueueClient(t *testing.T) { @@ -25,7 +26,7 @@ func TestSetQueueClient(t *testing.T) { ctx := context.Background() c := queue.QueueConfig{} err := c.SetQueueClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, c.QueueClient) } @@ -48,7 +49,7 @@ func TestPingQueueByURL(t *testing.T) { Return(&sqs.GetQueueAttributesOutput{}, nil) err := c.PingQueueByURL(ctx, url) - assert.NoError(t, err) + require.NoError(t, err) } func TestGetSQSEndpoint(t *testing.T) { cfg := queue.QueueConfig{} diff --git a/internal/serviceconfig/queue/delete_test.go b/internal/serviceconfig/queue/delete_test.go index f372b5d0..22801f1f 100644 --- a/internal/serviceconfig/queue/delete_test.go +++ b/internal/serviceconfig/queue/delete_test.go @@ -7,8 +7,9 @@ import ( "queryorchestration/internal/serviceconfig/queue" queuemock "queryorchestration/mocks/queue" + "github.com/stretchr/testify/require" + "github.com/aws/aws-sdk-go-v2/service/sqs" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -34,5 +35,5 @@ func TestDelete(t *testing.T) { Return(&sqs.DeleteMessageOutput{}, nil) err := cfg.DeleteFromQueue(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/serviceconfig/queue/documentclean/config.go b/internal/serviceconfig/queue/documentclean/config.go index 895668ba..e9af4ce5 100644 --- a/internal/serviceconfig/queue/documentclean/config.go +++ b/internal/serviceconfig/queue/documentclean/config.go @@ -1,5 +1,7 @@ package documentclean +const EnvName = "DOCUMENT_CLEAN_URL" + type DocCleanConfig struct { DocumentCleanURL string `env:"DOCUMENT_CLEAN_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/documentinit/config.go b/internal/serviceconfig/queue/documentinit/config.go index e81cede9..ac2ddb0e 100644 --- a/internal/serviceconfig/queue/documentinit/config.go +++ b/internal/serviceconfig/queue/documentinit/config.go @@ -1,5 +1,7 @@ package documentinit +const EnvName = "DOCUMENT_INIT_URL" + type DocInitConfig struct { DocInitURL string `env:"DOCUMENT_INIT_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/documentsync/config.go b/internal/serviceconfig/queue/documentsync/config.go index 8f804538..83227cd8 100644 --- a/internal/serviceconfig/queue/documentsync/config.go +++ b/internal/serviceconfig/queue/documentsync/config.go @@ -1,5 +1,7 @@ package documentsync +const EnvName = "DOCUMENT_SYNC_URL" + type DocSyncConfig struct { DocumentSyncURL string `env:"DOCUMENT_SYNC_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/documenttext/config.go b/internal/serviceconfig/queue/documenttext/config.go index 9f4d7f6c..cd12b180 100644 --- a/internal/serviceconfig/queue/documenttext/config.go +++ b/internal/serviceconfig/queue/documenttext/config.go @@ -1,5 +1,7 @@ package documenttext +const EnvName = "DOCUMENT_TEXT_URL" + type DocTextConfig struct { DocumentTextURL string `env:"DOCUMENT_TEXT_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/query/config.go b/internal/serviceconfig/queue/query/config.go index 0c7e5544..0744f2dc 100644 --- a/internal/serviceconfig/queue/query/config.go +++ b/internal/serviceconfig/queue/query/config.go @@ -1,5 +1,7 @@ package query +const EnvName = "QUERY_URL" + type QueryConfig struct { QueryURL string `env:"QUERY_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/querysync/config.go b/internal/serviceconfig/queue/querysync/config.go index fa0cc323..ca17c898 100644 --- a/internal/serviceconfig/queue/querysync/config.go +++ b/internal/serviceconfig/queue/querysync/config.go @@ -1,5 +1,7 @@ package querysync +const EnvName = "QUERY_SYNC_URL" + type QuerySyncConfig struct { QuerySyncURL string `env:"QUERY_SYNC_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/queryversionsync/config.go b/internal/serviceconfig/queue/queryversionsync/config.go index 5c140330..88db2da4 100644 --- a/internal/serviceconfig/queue/queryversionsync/config.go +++ b/internal/serviceconfig/queue/queryversionsync/config.go @@ -1,5 +1,7 @@ package queryversionsync +const EnvName = "QUERY_VERSION_SYNC_URL" + type QueryVersionSyncConfig struct { QueryVersionSyncURL string `env:"QUERY_VERSION_SYNC_URL,required,notEmpty"` } diff --git a/internal/serviceconfig/queue/receive.go b/internal/serviceconfig/queue/receive.go index 0f3e09aa..98416391 100644 --- a/internal/serviceconfig/queue/receive.go +++ b/internal/serviceconfig/queue/receive.go @@ -15,8 +15,8 @@ func (c *QueueConfig) ReceiveFromQueue(ctx context.Context, params *ReceiveParam return c.QueueClient.ReceiveMessage(ctx, &sqs.ReceiveMessageInput{ QueueUrl: ¶ms.QueueURL, MaxNumberOfMessages: 1, - WaitTimeSeconds: 30, - VisibilityTimeout: 5, + WaitTimeSeconds: 10, + VisibilityTimeout: 10, MessageAttributeNames: params.Attributes, }) } diff --git a/internal/serviceconfig/queue/receive_test.go b/internal/serviceconfig/queue/receive_test.go index ab0007e2..77175a55 100644 --- a/internal/serviceconfig/queue/receive_test.go +++ b/internal/serviceconfig/queue/receive_test.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestReceive(t *testing.T) { @@ -35,6 +36,6 @@ func TestReceive(t *testing.T) { Return(&res, nil) ares, err := cfg.ReceiveFromQueue(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualExportedValues(t, res, *ares) } diff --git a/internal/serviceconfig/queue/send_test.go b/internal/serviceconfig/queue/send_test.go index f3576157..f17c67f7 100644 --- a/internal/serviceconfig/queue/send_test.go +++ b/internal/serviceconfig/queue/send_test.go @@ -8,8 +8,8 @@ import ( queuemock "queryorchestration/mocks/queue" "github.com/aws/aws-sdk-go-v2/service/sqs" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestSend(t *testing.T) { @@ -33,5 +33,5 @@ func TestSend(t *testing.T) { Return(&sqs.SendMessageOutput{}, nil) err := cfg.SendToQueue(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/test/service.go b/internal/test/api.go similarity index 51% rename from internal/test/service.go rename to internal/test/api.go index 391055e8..9d91aa41 100644 --- a/internal/test/service.go +++ b/internal/test/api.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - queryservice "queryorchestration/api/queryService" + queryapi "queryorchestration/api/queryAPI" "queryorchestration/internal/serviceconfig" "github.com/docker/go-connections/nat" @@ -13,29 +13,33 @@ import ( "github.com/testcontainers/testcontainers-go" ) -type Service = string +type APIName = string const ( - QueryService = queryservice.Name + QueryAPIName APIName = queryapi.Name ) -type ServiceConfig struct { - Name Service - Cfg serviceconfig.ConfigProvider - Network *testcontainers.DockerNetwork - Env map[string]string +type API struct { + Name APIName + DownstreamQueues []RunnerName } -func CreateService(t testing.TB, ctx context.Context, config *ServiceConfig) (*Container, func()) { +type APIConfig struct { + API API + Cfg serviceconfig.ConfigProvider + Network *testcontainers.DockerNetwork +} + +func CreateAPI(t testing.TB, ctx context.Context, config *APIConfig) (*Container, func()) { port, err := nat.NewPort("tcp", "8080") require.NoError(t, err) container, cleanup := createContainer(t, ctx, &containerConfig{ - Cfg: config.Cfg, - Name: config.Name, - Network: config.Network, - Env: config.Env, - WaitForMsg: "⇨ http server started on [::]:8080", + Cfg: config.Cfg, + Name: config.API.Name, + DownstreamQueues: config.API.DownstreamQueues, + Network: config.Network, + WaitForMsg: "⇨ http server started on [::]:8080", }) host, err := container.Host(ctx) @@ -50,3 +54,15 @@ func CreateService(t testing.TB, ctx context.Context, config *ServiceConfig) (*C Container: container, }, cleanup } + +var QueryAPI = API{ + Name: QueryAPIName, + DownstreamQueues: []RunnerName{ + ClientSyncRunnerName, + QueryVersionSyncRunnerName, + }, +} + +var apis = []API{ + QueryAPI, +} diff --git a/internal/test/service_test.go b/internal/test/api_test.go similarity index 71% rename from internal/test/service_test.go rename to internal/test/api_test.go index 8be68899..08663023 100644 --- a/internal/test/service_test.go +++ b/internal/test/api_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCreateService(t *testing.T) { +func TestCreateAPI(t *testing.T) { if testing.Short() { t.Skip("Skipping long test in short mode") } @@ -30,17 +30,13 @@ func TestCreateService(t *testing.T) { }) defer dbcleanup() - acfg := &test.ServiceConfig{ - Name: test.QueryService, + acfg := &test.APIConfig{ + API: test.QueryAPI, Cfg: cfg, Network: ncfg, - Env: map[string]string{ - "CLIENT_SYNC_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": "/here/there/every/where", - }, } - conn, cleanup := test.CreateService(t, ctx, acfg) + conn, cleanup := test.CreateAPI(t, ctx, acfg) assert.NotNil(t, conn) assert.NotNil(t, cleanup) diff --git a/internal/test/container.go b/internal/test/container.go index a0e6d2ca..34ca30aa 100644 --- a/internal/test/container.go +++ b/internal/test/container.go @@ -22,12 +22,13 @@ type Container struct { } type containerConfig struct { - Name string - Cfg serviceconfig.ConfigProvider - Network *testcontainers.DockerNetwork - Env map[string]string - WaitForMsg string - ExposedPorts []nat.Port + Name string + Cfg serviceconfig.ConfigProvider + Network *testcontainers.DockerNetwork + DownstreamQueues []RunnerName + Env map[string]string + WaitForMsg string + ExposedPorts []nat.Port } func createContainer(t testing.TB, ctx context.Context, cfg *containerConfig) (testcontainers.Container, func()) { @@ -46,6 +47,7 @@ func createContainer(t testing.TB, ctx context.Context, cfg *containerConfig) (t "AWS_ENDPOINT_URL_SQS": cfg.Cfg.GetAWSEndpoint(), "AWS_ENDPOINT_URL_S3": cfg.Cfg.GetAWSEndpoint(), "AWS_S3_USE_PATH_STYLE": strconv.FormatBool(true), + "LOG_LEVEL": "DEBUG", } if cfg.Env != nil { for k, v := range cfg.Env { @@ -53,6 +55,10 @@ func createContainer(t testing.TB, ctx context.Context, cfg *containerConfig) (t } } + for _, e := range cfg.DownstreamQueues { + env[GetRunnerEnvFromName(e)] = GetQueueURL(cfg.Cfg, e) + } + req := testcontainers.ContainerRequest{ Image: "queryorchestration:latest", Env: env, @@ -74,14 +80,7 @@ func createContainer(t testing.TB, ctx context.Context, cfg *containerConfig) (t Started: true, }) if err != nil { - logs, _ := container.Logs(ctx) - defer logs.Close() - - scanner := bufio.NewScanner(logs) - for scanner.Scan() { - line := scanner.Text() - slog.Error(line) - } + PrintContainerLogs(t, ctx, container) require.NoError(t, err) } @@ -93,3 +92,18 @@ func createContainer(t testing.TB, ctx context.Context, cfg *containerConfig) (t } } } + +func PrintContainerLogs(t testing.TB, ctx context.Context, container testcontainers.Container) { + logs, err := container.Logs(ctx) + defer func() { + err := logs.Close() + require.NoError(t, err) + }() + require.NoError(t, err) + + scanner := bufio.NewScanner(logs) + for scanner.Scan() { + line := scanner.Text() + slog.Error(line) + } +} diff --git a/internal/test/container_test.go b/internal/test/container_test.go index b4678eaf..5d756561 100644 --- a/internal/test/container_test.go +++ b/internal/test/container_test.go @@ -29,12 +29,10 @@ func TestCreateContainer(t *testing.T) { defer dbcleanup() ccfg := &containerConfig{ - Name: QueryService, - Cfg: cfg, - Network: ncfg, - Env: map[string]string{ - "EXAMPLE": "value", - }, + Name: QueryAPIName, + DownstreamQueues: QueryAPI.DownstreamQueues, + Cfg: cfg, + Network: ncfg, ExposedPorts: []nat.Port{ nat.Port("8080/tcp"), }, @@ -44,5 +42,7 @@ func TestCreateContainer(t *testing.T) { assert.NotNil(t, container) assert.NotNil(t, cleanup) + PrintContainerLogs(t, ctx, container) + cleanup() } diff --git a/internal/test/ecosystem.go b/internal/test/ecosystem.go index 4e63cec3..b76a8583 100644 --- a/internal/test/ecosystem.go +++ b/internal/test/ecosystem.go @@ -10,104 +10,114 @@ import ( "queryorchestration/internal/serviceconfig/aws" "queryorchestration/internal/serviceconfig/database" "queryorchestration/internal/serviceconfig/objectstore" - queryservice "queryorchestration/pkg/queryService" + queryapi "queryorchestration/pkg/queryAPI" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" ) -type EcosystemConfig struct { - Services map[Service]*Container - Runners map[Runner]*Container - Cfg serviceconfig.ConfigProvider +type Network struct { + Dependencies Dependencies + APIs map[string]*Container + Runners map[string]*Container + Client *queryapi.ClientWithResponses } -type EcosystemNetworkConfig struct { - Runners []*RunnerNetworkConfig - Services []*ServiceNetworkConfig - Cfg serviceconfig.ConfigProvider - Dependencies *Dependencies +func CreateFullNetwork(t testing.TB, ctx context.Context, cfg FullDependenciesConfig) (Network, func()) { + deps, clean := CreateFullDependencies(t, ctx, cfg) + + apiContainers := make(map[string]*Container, len(apis)) + apiClean := make([]func(), len(apis)) + for i, s := range apis { + c, ccleanup := CreateAPI(t, ctx, &APIConfig{ + API: s, + Cfg: cfg, + Network: deps.Network, + }) + apiContainers[s.Name] = c + apiClean[i] = ccleanup + } + + qService, err := queryapi.NewClientWithResponses(apiContainers[QueryAPIName].URI) + require.NoError(t, err) + + runnerContainers := make(map[string]*Container, len(runners)) + runnerClean := make([]func(), len(runners)) + for i, r := range runners { + c, ccleanup := CreateRunner(t, ctx, &RunnerConfig{ + Runner: r, + Cfg: cfg, + Network: deps.Network, + }) + + runnerContainers[r.Name] = c + runnerClean[i] = ccleanup + } + + return Network{ + Dependencies: deps, + APIs: apiContainers, + Runners: runnerContainers, + Client: qService, + }, func() { + for _, c := range apiClean { + c() + } + for _, c := range runnerClean { + c() + } + clean() + } } -func CreateRunnersAndServicesNetwork(t testing.TB, ctx context.Context, ncfg *EcosystemNetworkConfig) (*EcosystemConfig, func()) { - if ncfg.Dependencies == nil { - ncfg.Dependencies = &Dependencies{} - } +type FullDependenciesConfig interface { + serviceconfig.ConfigProvider + objectstore.ConfigProvider +} - network := ncfg.Dependencies.Network - var ncleanup func() - if network == nil { - network, ncleanup = CreateNetwork(t, ctx) - } +type Dependencies struct { + BucketName string + QueueURLs map[string]string + Network *testcontainers.DockerNetwork + AWSConfig *AWSContainerConfig + DBConfig testcontainers.Container +} - _, dbcleanup := CreateDB(t, ctx, &CreateDatabaseConfig{ +func CreateFullDependencies(t testing.TB, ctx context.Context, cfg FullDependenciesConfig) (Dependencies, func()) { + network, ncleanup := CreateNetwork(t, ctx) + + acfg, awsclean := CreateAWSContainer(t, ctx, &CreateAWSConfig{ + Cfg: cfg, + Network: network, + }) + + dbcfg, dbcleanup := CreateDB(t, ctx, &CreateDatabaseConfig{ Network: network, - Cfg: ncfg.Cfg, + Cfg: cfg, RunMigrations: true, }) - ss := make(map[string]*Container, len(ncfg.Services)) - sclean := make([]func(), len(ncfg.Services)) - for i, s := range ncfg.Services { - c, ccleanup := CreateService(t, ctx, &ServiceConfig{ - Name: s.Name, - Env: s.Env, - Cfg: ncfg.Cfg, - Network: network, - }) - ss[s.Name] = c - sclean[i] = ccleanup + SetQueueClient(t, ctx, cfg) + SetStoreClient(t, ctx, cfg, acfg.ExternalEndpoint) + + urls := map[string]string{} + for _, runner := range runners { + urls[runner.Name] = CreateQueue(t, ctx, cfg, runner.Name) } - var qcleanup func() - if ncfg.Dependencies.AWSConfig == nil { - _, qcleanup = CreateAWSContainer(t, ctx, &CreateAWSConfig{ - Network: network, - Cfg: ncfg.Cfg, - }) - } + CreateBucket(t, ctx, cfg, BucketName) + SetBucketNotifs(t, ctx, cfg, BucketName) - if ncfg.Cfg.GetQueueClient() == nil { - SetQueueClient(t, ctx, ncfg.Cfg) - } - - qs := make(map[string]*Container, len(ncfg.Runners)) - qclean := make([]func(), len(ncfg.Runners)) - for i, r := range ncfg.Runners { - url := ncfg.Dependencies.QueueURLs[r.Name] - if url == "" { - url = CreateQueue(t, ctx, ncfg.Cfg, r.Name) - } - - c, ccleanup := CreateRunner(t, ctx, &RunnerConfig{ - Name: r.Name, - Env: r.Env, - QueueURL: url, - Cfg: ncfg.Cfg, - Network: network, - }) - - qs[r.Name] = c - qclean[i] = ccleanup - } - - return &EcosystemConfig{ - Services: ss, - Runners: qs, + return Dependencies{ + BucketName: BucketName, + QueueURLs: urls, + Network: network, + AWSConfig: acfg, + DBConfig: dbcfg, }, func() { - for _, c := range sclean { - c() - } - for _, c := range qclean { - c() - } + awsclean() dbcleanup() - if qcleanup != nil { - qcleanup() - } - if ncleanup != nil { - ncleanup() - } + ncleanup() } } @@ -142,11 +152,10 @@ func SetCfgProvider(t testing.TB, cfg serviceconfig.ConfigProvider) { type ServiceNetworkConfig struct { Cfg serviceconfig.ConfigProvider Network *testcontainers.DockerNetwork - Name Runner - Env map[string]string + API API } -func CreateServiceNetwork(t testing.TB, ctx context.Context, scfg *ServiceNetworkConfig) (*Container, func()) { +func CreateAPINetwork(t testing.TB, ctx context.Context, scfg *ServiceNetworkConfig) (*Container, func()) { if scfg.Cfg == nil { scfg.Cfg = &serviceconfig.BaseConfig{} SetCfgProvider(t, scfg.Cfg) @@ -163,9 +172,8 @@ func CreateServiceNetwork(t testing.TB, ctx context.Context, scfg *ServiceNetwor Cfg: scfg.Cfg, }) - c, ccleanup := CreateService(t, ctx, &ServiceConfig{ - Name: scfg.Name, - Env: scfg.Env, + c, ccleanup := CreateAPI(t, ctx, &APIConfig{ + API: scfg.API, Cfg: scfg.Cfg, Network: network, }) @@ -178,197 +186,3 @@ func CreateServiceNetwork(t testing.TB, ctx context.Context, scfg *ServiceNetwor } } } - -type RunnerNetworkConfig struct { - Network *testcontainers.DockerNetwork - AWSContainer *AWSContainerConfig - QueueURL *string - Cfg serviceconfig.ConfigProvider - Name Runner - Env map[string]string -} - -func CreateRunnerNetwork(t testing.TB, ctx context.Context, rcfg *RunnerNetworkConfig) (*Container, func()) { - network := rcfg.Network - var ncleanup func() - if network == nil { - network, ncleanup = CreateNetwork(t, ctx) - } - - var qcleanup func() - if rcfg.AWSContainer == nil { - _, qcleanup = CreateAWSContainer(t, ctx, &CreateAWSConfig{ - Network: network, - Cfg: rcfg.Cfg, - }) - } - - if rcfg.Cfg.GetQueueClient() == nil { - err := rcfg.Cfg.SetQueueClient(ctx) - require.NoError(t, err) - } - - url := rcfg.QueueURL - if url == nil { - u := CreateQueue(t, ctx, rcfg.Cfg, rcfg.Name) - url = &u - } - - _, dbcleanup := CreateDB(t, ctx, &CreateDatabaseConfig{ - Network: network, - Cfg: rcfg.Cfg, - }) - - c, ccleanup := CreateRunner(t, ctx, &RunnerConfig{ - Name: rcfg.Name, - Env: rcfg.Env, - QueueURL: *url, - Cfg: rcfg.Cfg, - Network: network, - }) - - return c, func() { - ccleanup() - dbcleanup() - if qcleanup != nil { - qcleanup() - } - if ncleanup != nil { - ncleanup() - } - } -} - -type FullDependenciesConfig interface { - serviceconfig.ConfigProvider - objectstore.ConfigProvider -} - -type Dependencies struct { - BucketName string - QueueURLs map[string]string - Network *testcontainers.DockerNetwork - AWSConfig *AWSContainerConfig -} - -func CreateFullDependencies(t testing.TB, ctx context.Context, cfg FullDependenciesConfig) (Dependencies, func()) { - network, ncleanup := CreateNetwork(t, ctx) - - acfg, clean := CreateAWSContainer(t, ctx, &CreateAWSConfig{ - Cfg: cfg, - Network: network, - }) - - SetQueueClient(t, ctx, cfg) - SetStoreClient(t, ctx, cfg, acfg.ExternalEndpoint) - - urls := map[string]string{} - urls[DocInitRunner] = CreateQueue(t, ctx, cfg, DocInitRunner) - urls[DocSyncRunner] = CreateQueue(t, ctx, cfg, DocSyncRunner) - urls[DocCleanRunner] = CreateQueue(t, ctx, cfg, DocCleanRunner) - urls[DocTextRunner] = CreateQueue(t, ctx, cfg, DocTextRunner) - urls[QuerySyncRunner] = CreateQueue(t, ctx, cfg, QuerySyncRunner) - urls[QueryRunner] = CreateQueue(t, ctx, cfg, QueryRunner) - urls[ClientSyncRunner] = CreateQueue(t, ctx, cfg, ClientSyncRunner) - urls[QueryVersionSyncRunner] = CreateQueue(t, ctx, cfg, QueryVersionSyncRunner) - - bucketName := "docinitbucket" - CreateBucket(t, ctx, cfg, bucketName) - SetBucketNotifs(t, ctx, cfg, bucketName) - - return Dependencies{ - BucketName: bucketName, - QueueURLs: urls, - Network: network, - AWSConfig: acfg, - }, func() { - ncleanup() - clean() - } -} - -type Network struct { - Dependencies Dependencies - Network EcosystemConfig - Client *queryservice.ClientWithResponses -} - -func CreateFullNetwork(t testing.TB, ctx context.Context, cfg FullDependenciesConfig) (Network, func()) { - deps, clean := CreateFullDependencies(t, ctx, cfg) - - net, cleanup := CreateRunnersAndServicesNetwork(t, ctx, &EcosystemNetworkConfig{ - Cfg: cfg, - Dependencies: &deps, - Runners: []*RunnerNetworkConfig{ - { - Name: DocInitRunner, - Env: map[string]string{ - "DOCUMENT_SYNC_URL": deps.QueueURLs[DocSyncRunner], - }, - }, - { - Name: DocSyncRunner, - Env: map[string]string{ - "DOCUMENT_CLEAN_URL": deps.QueueURLs[DocCleanRunner], - }, - }, - { - Name: DocCleanRunner, - Env: map[string]string{ - "DOCUMENT_TEXT_URL": deps.QueueURLs[DocTextRunner], - }, - }, - { - Name: DocTextRunner, - Env: map[string]string{ - "QUERY_SYNC_URL": deps.QueueURLs[QuerySyncRunner], - }, - }, - { - Name: QuerySyncRunner, - Env: map[string]string{ - "QUERY_URL": deps.QueueURLs[QueryRunner], - }, - }, - { - Name: QueryRunner, - Env: map[string]string{ - "QUERY_URL": deps.QueueURLs[QueryRunner], - }, - }, - { - Name: ClientSyncRunner, - Env: map[string]string{ - "DOCUMENT_SYNC_URL": deps.QueueURLs[DocSyncRunner], - }, - }, - { - Name: QueryVersionSyncRunner, - Env: map[string]string{ - "CLIENT_SYNC_URL": deps.QueueURLs[ClientSyncRunner], - }, - }, - }, - Services: []*ServiceNetworkConfig{ - { - Name: QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": deps.QueueURLs[ClientSyncRunner], - "QUERY_VERSION_SYNC_URL": deps.QueueURLs[QueryVersionSyncRunner], - }, - }, - }, - }) - - qService, err := queryservice.NewClientWithResponses(net.Services[QueryService].URI) - require.NoError(t, err) - - return Network{ - Dependencies: deps, - Network: *net, - Client: qService, - }, func() { - cleanup() - clean() - } -} diff --git a/internal/test/ecosystem_test.go b/internal/test/ecosystem_test.go index b41ceb53..758f7033 100644 --- a/internal/test/ecosystem_test.go +++ b/internal/test/ecosystem_test.go @@ -10,76 +10,14 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCreateRunnerNetwork(t *testing.T) { +func TestCreateAPINetwork(t *testing.T) { if testing.Short() { t.Skip("Skipping long test in short mode") } ctx := context.Background() - cfg := &serviceconfig.BaseConfig{} - SetCfgProvider(t, cfg) - conn, cleanup := CreateRunnerNetwork(t, ctx, &RunnerNetworkConfig{ - Cfg: cfg, - Name: QueryRunner, - Env: map[string]string{ - "QUERY_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": "/here/there/every/where", - }, - }) - - assert.NotNil(t, conn) - assert.NotNil(t, cleanup) - - cleanup() -} - -func TestCreateServiceNetwork(t *testing.T) { - if testing.Short() { - t.Skip("Skipping long test in short mode") - } - ctx := context.Background() - - conn, cleanup := CreateServiceNetwork(t, ctx, &ServiceNetworkConfig{ - Name: QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": "/here/there/every/where", - }, - }) - - assert.NotNil(t, conn) - assert.NotNil(t, cleanup) - - cleanup() -} - -func TestCreateRunnersAndServicesNetwork(t *testing.T) { - if testing.Short() { - t.Skip("Skipping long test in short mode") - } - ctx := context.Background() - cfg := &serviceconfig.BaseConfig{} - SetCfgProviderWithBasePath(t, cfg, "../..") - - conn, cleanup := CreateRunnersAndServicesNetwork(t, ctx, &EcosystemNetworkConfig{ - Cfg: cfg, - Runners: []*RunnerNetworkConfig{ - { - Name: QueryRunner, - Env: map[string]string{ - "QUERY_URL": "/i/am/here", - }, - }, - }, - Services: []*ServiceNetworkConfig{ - { - Name: QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": "/here/there/every/where", - }, - }, - }, + conn, cleanup := CreateAPINetwork(t, ctx, &ServiceNetworkConfig{ + API: QueryAPI, }) assert.NotNil(t, conn) diff --git a/internal/test/objectstore.go b/internal/test/objectstore.go index 07ef56dc..37564dde 100644 --- a/internal/test/objectstore.go +++ b/internal/test/objectstore.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "log/slog" "testing" objectstore "queryorchestration/internal/serviceconfig/objectstore" @@ -20,13 +21,16 @@ func CreateBucket(t testing.TB, ctx context.Context, cfg objectstore.ConfigProvi Bucket: aws.String(name), }) require.NoError(t, err) + slog.Info("create bucket", "bucket", name) err = cfg.PingStoreByName(ctx, name) require.NoError(t, err) } +const BucketName = "documentbucket" + func SetBucketNotifs(t testing.TB, ctx context.Context, cfg objectstore.ConfigProvider, name string) { - arn := fmt.Sprintf("arn:aws:sqs:%s:000000000000:%s", cfg.GetAWSRegion(), DocInitRunner) + arn := GetQueueArn(cfg, DocInitRunnerName) _, err := cfg.GetStoreClient().PutBucketNotificationConfiguration(ctx, &s3.PutBucketNotificationConfigurationInput{ Bucket: &name, NotificationConfiguration: &awstypes.NotificationConfiguration{ @@ -41,7 +45,7 @@ func SetBucketNotifs(t testing.TB, ctx context.Context, cfg objectstore.ConfigPr }, }) require.NoError(t, err) - + slog.Info("set bucket notifs", "bucket", name, "queueARN", arn) } func SetStoreClient(t testing.TB, ctx context.Context, cfg objectstore.ConfigProvider, endpoint string) { @@ -51,7 +55,7 @@ func SetStoreClient(t testing.TB, ctx context.Context, cfg objectstore.ConfigPro require.NoError(t, err) } -func PutObject(t testing.TB, ctx context.Context, cfg objectstore.ConfigProvider, clientId types.UUID, bucket string, filename string, file io.Reader) string { +func PutObject(t testing.TB, ctx context.Context, cfg objectstore.ConfigProvider, clientId types.UUID, bucket string, filename string, file io.Reader) { location := fmt.Sprintf("%s/%s", clientId, filename) _, err := cfg.GetStoreClient().PutObject(ctx, &s3.PutObjectInput{ Bucket: &bucket, @@ -59,6 +63,5 @@ func PutObject(t testing.TB, ctx context.Context, cfg objectstore.ConfigProvider Body: file, }) require.NoError(t, err) - - return location + slog.Info("put object", "bucket", bucket, "key", location) } diff --git a/internal/test/objectstore_test.go b/internal/test/objectstore_test.go index 55a41bdc..410fb709 100644 --- a/internal/test/objectstore_test.go +++ b/internal/test/objectstore_test.go @@ -82,6 +82,5 @@ func TestPutObject(t *testing.T) { ). Return(&s3.PutObjectOutput{}, nil) - location := PutObject(t, ctx, cfg, clientId, bucketName, filename, file) - assert.Equal(t, expectedLocation, location) + PutObject(t, ctx, cfg, clientId, bucketName, filename, file) } diff --git a/internal/test/queryAPI/service.go b/internal/test/queryAPI/service.go new file mode 100644 index 00000000..f0e4ef15 --- /dev/null +++ b/internal/test/queryAPI/service.go @@ -0,0 +1,63 @@ +package queryapitest + +import ( + "context" + "fmt" + "log/slog" + "testing" + "time" + + queryapi "queryorchestration/pkg/queryAPI" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func CreateClientWithSync(t testing.TB, ctx context.Context, client queryapi.ClientWithResponsesInterface) *queryapi.DocClient { + t.Helper() + + clientCreateRes, err := client.CreateClientWithResponse(ctx, queryapi.ClientCreate{ + Name: "example_name", + Id: "ID", + }) + require.NoError(t, err) + + canSync := true + _, err = client.UpdateClientWithResponse(ctx, clientCreateRes.JSON201.Id, queryapi.ClientUpdate{ + CanSync: &canSync, + }) + require.NoError(t, err) + + clientRes, err := client.GetClientWithResponse(ctx, clientCreateRes.JSON201.Id) + require.NoError(t, err) + + return clientRes.JSON200 +} + +func WaitForClientStatus(t testing.TB, ctx context.Context, service queryapi.ClientWithResponsesInterface, id string, status queryapi.ClientStatus) { + t.Helper() + + timeout := time.After(60 * time.Second) + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + + for { + select { + case <-timeout: + require.NoError(t, fmt.Errorf("Timeout waiting for client status to become %s", status)) + case <-ticker.C: + jRes, err := service.GetStatusByClientIdWithResponse(ctx, id) + if err != nil { + slog.Error("error getting status", "error", err.Error()) + require.NoError(t, err) + } + + if jRes.JSON200.Status == status { + assert.Equal(t, status, jRes.JSON200.Status) + return + } + + slog.Error("unexpected status", "status", jRes.JSON200.Status) + } + } +} diff --git a/internal/test/queryAPI/service_test.go b/internal/test/queryAPI/service_test.go new file mode 100644 index 00000000..f5c65588 --- /dev/null +++ b/internal/test/queryAPI/service_test.go @@ -0,0 +1,80 @@ +package queryapitest_test + +import ( + "context" + "testing" + + queryapitest "queryorchestration/internal/test/queryAPI" + queryapimock "queryorchestration/mocks/queryapi" + queryapi "queryorchestration/pkg/queryAPI" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestCreateClientWithSync(t *testing.T) { + ctx := context.Background() + + svcClient := queryapimock.NewMockClientWithResponsesInterface(t) + + svcClient.EXPECT().CreateClientWithResponse( + mock.Anything, + mock.MatchedBy(func(create queryapi.ClientCreate) bool { + return create.Name == "example_name" && create.Id == "ID" + }), + mock.Anything, + ).Return(&queryapi.CreateClientResponse{ + JSON201: &queryapi.ClientIDBody{ + Id: "ID", + }, + }, nil) + + svcClient.EXPECT().UpdateClientWithResponse( + mock.Anything, + mock.MatchedBy(func(id string) bool { + return id == "ID" + }), + mock.MatchedBy(func(create queryapi.ClientUpdate) bool { + return *create.CanSync == true + }), + mock.Anything, + ).Return(&queryapi.UpdateClientResponse{}, nil) + + svcClient.EXPECT().GetClientWithResponse( + mock.Anything, + mock.MatchedBy(func(id string) bool { + return id == "ID" + }), + mock.Anything, + ).Return(&queryapi.GetClientResponse{ + JSON200: &queryapi.DocClient{ + Id: "ID", + }, + }, nil) + + client := queryapitest.CreateClientWithSync(t, ctx, svcClient) + + assert.NotNil(t, client) + assert.NotNil(t, client) + assert.EqualExportedValues(t, queryapi.DocClient{ + Id: "ID", + }, *client) +} + +func TestWaitForClientStatus(t *testing.T) { + ctx := context.Background() + client := queryapimock.NewMockClientWithResponsesInterface(t) + + client.EXPECT().GetStatusByClientIdWithResponse( + mock.Anything, + mock.MatchedBy(func(id string) bool { + return id == "id" + }), + ).Return(&queryapi.GetStatusByClientIdResponse{ + JSON200: &queryapi.ClientStatusBody{ + Status: queryapi.INSYNC, + }, + }, nil) + + queryapitest.WaitForClientStatus(t, ctx, client, "id", queryapi.INSYNC) +} diff --git a/internal/test/queryService/service.go b/internal/test/queryService/service.go deleted file mode 100644 index 7d6ab2f4..00000000 --- a/internal/test/queryService/service.go +++ /dev/null @@ -1,29 +0,0 @@ -package queryservicetest - -import ( - "context" - "testing" - - queryservice "queryorchestration/pkg/queryService" - - "github.com/stretchr/testify/require" -) - -func CreateClientWithSync(t testing.TB, ctx context.Context, client queryservice.ClientWithResponsesInterface) *queryservice.DocClient { - clientCreateRes, err := client.CreateClientWithResponse(ctx, queryservice.ClientCreate{ - Name: "example_name", - Id: "ID", - }) - require.NoError(t, err) - - canSync := true - _, err = client.UpdateClientWithResponse(ctx, clientCreateRes.JSON201.Id, queryservice.ClientUpdate{ - CanSync: &canSync, - }) - require.NoError(t, err) - - clientRes, err := client.GetClientWithResponse(ctx, clientCreateRes.JSON201.Id) - require.NoError(t, err) - - return clientRes.JSON200 -} diff --git a/internal/test/queryService/service_test.go b/internal/test/queryService/service_test.go deleted file mode 100644 index ecde52c7..00000000 --- a/internal/test/queryService/service_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package queryservicetest_test - -import ( - "context" - "testing" - - queryservicetest "queryorchestration/internal/test/queryService" - queryservicemock "queryorchestration/mocks/queryservice" - queryservice "queryorchestration/pkg/queryService" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -func TestCreateClientWithSync(t *testing.T) { - ctx := context.Background() - - svcClient := queryservicemock.NewMockClientWithResponsesInterface(t) - - svcClient.EXPECT().CreateClientWithResponse( - mock.Anything, - mock.MatchedBy(func(create queryservice.ClientCreate) bool { - return create.Name == "example_name" && create.Id == "ID" - }), - mock.Anything, - ).Return(&queryservice.CreateClientResponse{ - JSON201: &queryservice.ClientIDBody{ - Id: "ID", - }, - }, nil) - - svcClient.EXPECT().UpdateClientWithResponse( - mock.Anything, - mock.MatchedBy(func(id string) bool { - return id == "ID" - }), - mock.MatchedBy(func(create queryservice.ClientUpdate) bool { - return *create.CanSync == true - }), - mock.Anything, - ).Return(&queryservice.UpdateClientResponse{}, nil) - - svcClient.EXPECT().GetClientWithResponse( - mock.Anything, - mock.MatchedBy(func(id string) bool { - return id == "ID" - }), - mock.Anything, - ).Return(&queryservice.GetClientResponse{ - JSON200: &queryservice.DocClient{ - Id: "ID", - }, - }, nil) - - client := queryservicetest.CreateClientWithSync(t, ctx, svcClient) - - assert.NotNil(t, client) - assert.NotNil(t, client) - assert.EqualExportedValues(t, queryservice.DocClient{ - Id: "ID", - }, *client) -} diff --git a/internal/test/queue.go b/internal/test/queue.go index 091489e3..5718fa99 100644 --- a/internal/test/queue.go +++ b/internal/test/queue.go @@ -2,12 +2,16 @@ package test import ( "context" + "fmt" + "log/slog" "regexp" "testing" "queryorchestration/internal/serviceconfig" "queryorchestration/internal/serviceconfig/queue" + awsc "queryorchestration/internal/serviceconfig/aws" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/aws/aws-sdk-go-v2/service/sqs/types" @@ -20,11 +24,20 @@ func SetQueueClient(t testing.TB, ctx context.Context, cfg queue.ConfigProvider) require.NoError(t, err) } +func GetQueueURL(cfg awsc.ConfigProvider, name RunnerName) string { + return fmt.Sprintf("http://localstack:4566/queue/%s/000000000000/%s", cfg.GetAWSRegion(), name) +} + +func GetQueueArn(cfg awsc.ConfigProvider, name RunnerName) string { + return fmt.Sprintf("arn:aws:sqs:%s:000000000000:%s", cfg.GetAWSRegion(), name) +} + func CreateQueue(t testing.TB, ctx context.Context, cfg serviceconfig.ConfigProvider, name string) string { queueM, err := cfg.GetQueueClient().CreateQueue(ctx, &sqs.CreateQueueInput{ QueueName: aws.String(name), }) require.NoError(t, err) + slog.Info("create queue", "name", name, "url", *queueM.QueueUrl) err = cfg.PingQueueByURL(ctx, *queueM.QueueUrl) require.NoError(t, err) @@ -34,7 +47,7 @@ func CreateQueue(t testing.TB, ctx context.Context, cfg serviceconfig.ConfigProv func AssertMessage(t testing.TB, ctx context.Context, cfg serviceconfig.ConfigProvider, params *queue.ReceiveParams) types.Message { result, err := cfg.ReceiveFromQueue(ctx, params) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, result.Messages) assert.Len(t, result.Messages, 1) assert.NotNil(t, result.Messages[0]) diff --git a/internal/test/queue_test.go b/internal/test/queue_test.go index 9abfef33..f528915d 100644 --- a/internal/test/queue_test.go +++ b/internal/test/queue_test.go @@ -8,9 +8,12 @@ import ( "queryorchestration/internal/serviceconfig" "queryorchestration/internal/serviceconfig/queue" + awsc "queryorchestration/internal/serviceconfig/aws" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/sqs/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCreateQueue(t *testing.T) { @@ -28,7 +31,7 @@ func TestCreateQueue(t *testing.T) { defer cleanup() err := cfg.SetQueueClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) url := CreateQueue(t, ctx, cfg, "myname") assert.Equal(t, "http://localstack:4566/queue/us-east-1/000000000000/myname", url) @@ -48,14 +51,14 @@ func TestAssertMessageWait(t *testing.T) { }) defer cleanup() err := cfg.SetQueueClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) url := CreateQueue(t, ctx, cfg, "myname") err = cfg.SendToQueue(ctx, &queue.SendParams{ QueueURL: url, Body: "body", }) - assert.NoError(t, err) + require.NoError(t, err) msg := AssertMessage(t, ctx, cfg, &queue.ReceiveParams{ QueueURL: url, @@ -77,14 +80,14 @@ func TestAssertMessageBodyWait(t *testing.T) { }) defer cleanup() err := cfg.SetQueueClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) url := CreateQueue(t, ctx, cfg, "myname") err = cfg.SendToQueue(ctx, &queue.SendParams{ QueueURL: url, Body: "body", }) - assert.NoError(t, err) + require.NoError(t, err) AssertMessageBody(t, ctx, cfg, url, regexp.MustCompile("\"body\"")) } @@ -103,7 +106,7 @@ func TestAssertMessageAttrWait(t *testing.T) { }) defer cleanup() err := cfg.SetQueueClient(ctx) - assert.NoError(t, err) + require.NoError(t, err) url := CreateQueue(t, ctx, cfg, "myname") name := "name" @@ -119,7 +122,21 @@ func TestAssertMessageAttrWait(t *testing.T) { }, }, }) - assert.NoError(t, err) + require.NoError(t, err) AssertMessageAttr(t, ctx, cfg, url, name, regexp.MustCompile(value)) } + +func TestGetQueueURL(t *testing.T) { + cfg := &awsc.AWSConfig{ + AWSRegion: "us-east-1", + } + assert.Equal(t, "http://localstack:4566/queue/us-east-1/000000000000/docInitRunner", GetQueueURL(cfg, DocInitRunnerName)) +} + +func TestGetQueueARN(t *testing.T) { + cfg := &awsc.AWSConfig{ + AWSRegion: "us-east-1", + } + assert.Equal(t, "arn:aws:sqs:us-east-1:000000000000:docInitRunner", GetQueueArn(cfg, DocInitRunnerName)) +} diff --git a/internal/test/runner.go b/internal/test/runner.go index 24efbdd1..b5a7e18d 100644 --- a/internal/test/runner.go +++ b/internal/test/runner.go @@ -14,47 +14,135 @@ import ( queryversionsyncrunner "queryorchestration/api/queryVersionSyncRunner" "queryorchestration/internal/serviceconfig" + "queryorchestration/internal/serviceconfig/queue/clientsync" + "queryorchestration/internal/serviceconfig/queue/documentclean" + "queryorchestration/internal/serviceconfig/queue/documentinit" + "queryorchestration/internal/serviceconfig/queue/documentsync" + "queryorchestration/internal/serviceconfig/queue/documenttext" + "queryorchestration/internal/serviceconfig/queue/query" + "queryorchestration/internal/serviceconfig/queue/querysync" + "queryorchestration/internal/serviceconfig/queue/queryversionsync" "github.com/testcontainers/testcontainers-go" ) -type Runner = string +type RunnerName = string const ( - DocInitRunner = docinitrunner.Name - DocSyncRunner = docsyncrunner.Name - DocCleanRunner = doccleanrunner.Name - DocTextRunner = doctextrunner.Name - QuerySyncRunner = querysyncrunner.Name - QueryRunner = queryrunner.Name - ClientSyncRunner = clientsyncrunner.Name - QueryVersionSyncRunner = queryversionsyncrunner.Name + DocInitRunnerName RunnerName = docinitrunner.Name + DocSyncRunnerName RunnerName = docsyncrunner.Name + DocCleanRunnerName RunnerName = doccleanrunner.Name + DocTextRunnerName RunnerName = doctextrunner.Name + QuerySyncRunnerName RunnerName = querysyncrunner.Name + QueryRunnerName RunnerName = queryrunner.Name + ClientSyncRunnerName RunnerName = clientsyncrunner.Name + QueryVersionSyncRunnerName RunnerName = queryversionsyncrunner.Name ) +type RunnerEnv = string + +const ( + DocInitRunnerEnv RunnerEnv = documentinit.EnvName + DocSyncRunnerEnv RunnerEnv = documentsync.EnvName + DocCleanRunnerEnv RunnerEnv = documentclean.EnvName + DocTextRunnerEnv RunnerEnv = documenttext.EnvName + QuerySyncRunnerEnv RunnerEnv = querysync.EnvName + QueryRunnerEnv RunnerEnv = query.EnvName + ClientSyncRunnerEnv RunnerEnv = clientsync.EnvName + QueryVersionSyncRunnerEnv RunnerEnv = queryversionsync.EnvName +) + +type Runner struct { + Name RunnerName + DownstreamQueues []RunnerName +} + +func GetRunnerEnvFromName(name RunnerName) RunnerEnv { + switch name { + case DocSyncRunnerName: + return DocSyncRunnerEnv + case DocCleanRunnerName: + return DocCleanRunnerEnv + case DocTextRunnerName: + return DocTextRunnerEnv + case QuerySyncRunnerName: + return QuerySyncRunnerEnv + case QueryRunnerName: + return QueryRunnerEnv + case ClientSyncRunnerName: + return ClientSyncRunnerEnv + case QueryVersionSyncRunnerName: + return QueryVersionSyncRunnerEnv + } + return DocInitRunnerEnv +} + type RunnerConfig struct { - Name Runner - QueueURL string - Cfg serviceconfig.ConfigProvider - Network *testcontainers.DockerNetwork - Env map[string]string + Runner Runner + Cfg serviceconfig.ConfigProvider + Network *testcontainers.DockerNetwork } func CreateRunner(t testing.TB, ctx context.Context, config *RunnerConfig) (*Container, func()) { - if config.Env == nil { - config.Env = map[string]string{} - } - config.Env["QUEUE_URL"] = config.QueueURL + env := map[string]string{} + url := GetQueueURL(config.Cfg, config.Runner.Name) + env["QUEUE_URL"] = url c, cleanup := createContainer(t, ctx, &containerConfig{ - Network: config.Network, - Name: config.Name, - Cfg: config.Cfg, - Env: config.Env, - WaitForMsg: "Listening to queue", + Network: config.Network, + Name: config.Runner.Name, + DownstreamQueues: config.Runner.DownstreamQueues, + Cfg: config.Cfg, + Env: env, + WaitForMsg: "Listening to queue", }) return &Container{ Container: c, - URI: config.QueueURL, + URI: url, }, cleanup } + +var DocInitRunner = Runner{ + Name: DocInitRunnerName, + DownstreamQueues: []RunnerName{DocSyncRunnerName}, +} +var DocSyncRunner = Runner{ + Name: DocSyncRunnerName, + DownstreamQueues: []RunnerName{DocCleanRunnerName}, +} +var DocCleanRunner = Runner{ + Name: DocCleanRunnerName, + DownstreamQueues: []RunnerName{DocTextRunnerName}, +} +var DocTextRunner = Runner{ + Name: DocTextRunnerName, + DownstreamQueues: []RunnerName{QuerySyncRunnerName}, +} +var QuerySyncRunner = Runner{ + Name: QuerySyncRunnerName, + DownstreamQueues: []RunnerName{QueryRunnerName}, +} +var QueryRunner = Runner{ + Name: QueryRunnerName, + DownstreamQueues: []RunnerName{QueryRunnerName}, +} +var ClientSyncRunner = Runner{ + Name: ClientSyncRunnerName, + DownstreamQueues: []RunnerName{DocSyncRunnerName}, +} +var QueryVersionSyncRunner = Runner{ + Name: QueryVersionSyncRunnerName, + DownstreamQueues: []RunnerName{ClientSyncRunnerName}, +} + +var runners = []Runner{ + DocInitRunner, + DocSyncRunner, + DocCleanRunner, + DocTextRunner, + QuerySyncRunner, + QueryRunner, + ClientSyncRunner, + QueryVersionSyncRunner, +} diff --git a/internal/test/runner_test.go b/internal/test/runner_test.go index 925839b4..8badb446 100644 --- a/internal/test/runner_test.go +++ b/internal/test/runner_test.go @@ -7,6 +7,7 @@ import ( "queryorchestration/internal/serviceconfig" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCreateRunner(t *testing.T) { @@ -27,8 +28,8 @@ func TestCreateRunner(t *testing.T) { }) defer qcleanup() err := cfg.SetQueueClient(ctx) - assert.NoError(t, err) - url := CreateQueue(t, ctx, cfg, "myname") + require.NoError(t, err) + _ = CreateQueue(t, ctx, cfg, QueryRunnerName) _, dbcleanup := CreateDB(t, ctx, &CreateDatabaseConfig{ Network: ncfg, @@ -37,13 +38,9 @@ func TestCreateRunner(t *testing.T) { defer dbcleanup() qccfg := &RunnerConfig{ - Name: QueryRunner, - Cfg: cfg, - Network: ncfg, - QueueURL: url, - Env: map[string]string{ - "QUERY_URL": "/i/am/here", - }, + Runner: QueryRunner, + Cfg: cfg, + Network: ncfg, } c, cleanup := CreateRunner(t, ctx, qccfg) @@ -52,3 +49,15 @@ func TestCreateRunner(t *testing.T) { cleanup() } + +func TestGetRunnerEnvFromName(t *testing.T) { + assert.Equal(t, DocInitRunnerEnv, GetRunnerEnvFromName(DocInitRunnerName)) + assert.Equal(t, DocSyncRunnerEnv, GetRunnerEnvFromName(DocSyncRunnerName)) + assert.Equal(t, DocCleanRunnerEnv, GetRunnerEnvFromName(DocCleanRunnerName)) + assert.Equal(t, DocTextRunnerEnv, GetRunnerEnvFromName(DocTextRunnerName)) + assert.Equal(t, QuerySyncRunnerEnv, GetRunnerEnvFromName(QuerySyncRunnerName)) + assert.Equal(t, QueryRunnerEnv, GetRunnerEnvFromName(QueryRunnerName)) + assert.Equal(t, ClientSyncRunnerEnv, GetRunnerEnvFromName(ClientSyncRunnerName)) + assert.Equal(t, QueryVersionSyncRunnerEnv, GetRunnerEnvFromName(QueryVersionSyncRunnerName)) + assert.Equal(t, DocInitRunnerEnv, GetRunnerEnvFromName(DocInitRunnerName)) +} diff --git a/internal/validation/validation_test.go b/internal/validation/validation_test.go index ffe56c99..eb8f18e1 100644 --- a/internal/validation/validation_test.go +++ b/internal/validation/validation_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGetUpdatedValue(t *testing.T) { @@ -30,17 +31,17 @@ func TestDeduplicateArray(t *testing.T) { func TestNormalizeInClosedInterval(t *testing.T) { err := validation.NormalizeInClosedInterval(nil, 1, 1, 1) - assert.NoError(t, err) + require.NoError(t, err) var param *int32 err = validation.NormalizeInClosedInterval(¶m, 1, 1, 1) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, param) updated := int32(1) param = &updated err = validation.NormalizeInClosedInterval(¶m, 1, 1, 1) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, param) assert.Equal(t, int32(1), updated) @@ -57,7 +58,7 @@ func TestNormalizeInClosedInterval(t *testing.T) { updated = 2 param = &updated err = validation.NormalizeInClosedInterval(¶m, 1, 1, 3) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int32(2), updated) } @@ -175,7 +176,7 @@ func TestGetFieldName(t *testing.T) { fieldone: nil, } name, err := validation.GetFieldName(val, val.fieldone) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "fieldone", name) }) t.Run("valid field is populated", func(t *testing.T) { @@ -187,7 +188,7 @@ func TestGetFieldName(t *testing.T) { fieldone: &strval, } name, err := validation.GetFieldName(val, val.fieldone) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "fieldone", name) }) } diff --git a/mocks/queryservice/mock_ClientInterface.go b/mocks/queryapi/mock_ClientInterface.go similarity index 71% rename from mocks/queryservice/mock_ClientInterface.go rename to mocks/queryapi/mock_ClientInterface.go index 8430a69d..57a4d549 100644 --- a/mocks/queryservice/mock_ClientInterface.go +++ b/mocks/queryapi/mock_ClientInterface.go @@ -1,6 +1,6 @@ // Code generated by mockery v2.52.3. DO NOT EDIT. -package queryservicemock +package queryapimock import ( context "context" @@ -10,7 +10,7 @@ import ( mock "github.com/stretchr/testify/mock" - queryservice "queryorchestration/pkg/queryService" + queryapi "queryorchestration/pkg/queryAPI" uuid "github.com/google/uuid" ) @@ -29,7 +29,7 @@ func (_m *MockClientInterface) EXPECT() *MockClientInterface_Expecter { } // CreateClient provides a mock function with given fields: ctx, body, reqEditors -func (_m *MockClientInterface) CreateClient(ctx context.Context, body queryservice.ClientCreate, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) CreateClient(ctx context.Context, body queryapi.ClientCreate, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -45,10 +45,10 @@ func (_m *MockClientInterface) CreateClient(ctx context.Context, body queryservi var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -56,7 +56,7 @@ func (_m *MockClientInterface) CreateClient(ctx context.Context, body queryservi } } - if rf, ok := ret.Get(1).(func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, body, reqEditors...) } else { r1 = ret.Error(1) @@ -72,22 +72,22 @@ type MockClientInterface_CreateClient_Call struct { // CreateClient is a helper method to define mock.On call // - ctx context.Context -// - body queryservice.ClientCreate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.ClientCreate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) CreateClient(ctx interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_CreateClient_Call { return &MockClientInterface_CreateClient_Call{Call: _e.mock.On("CreateClient", append([]interface{}{ctx, body}, reqEditors...)...)} } -func (_c *MockClientInterface_CreateClient_Call) Run(run func(ctx context.Context, body queryservice.ClientCreate, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_CreateClient_Call { +func (_c *MockClientInterface_CreateClient_Call) Run(run func(ctx context.Context, body queryapi.ClientCreate, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_CreateClient_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(queryservice.ClientCreate), variadicArgs...) + run(args[0].(context.Context), args[1].(queryapi.ClientCreate), variadicArgs...) }) return _c } @@ -97,13 +97,13 @@ func (_c *MockClientInterface_CreateClient_Call) Return(_a0 *http.Response, _a1 return _c } -func (_c *MockClientInterface_CreateClient_Call) RunAndReturn(run func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateClient_Call { +func (_c *MockClientInterface_CreateClient_Call) RunAndReturn(run func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateClient_Call { _c.Call.Return(run) return _c } // CreateClientWithBody provides a mock function with given fields: ctx, contentType, body, reqEditors -func (_m *MockClientInterface) CreateClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) CreateClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -119,10 +119,10 @@ func (_m *MockClientInterface) CreateClientWithBody(ctx context.Context, content var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -130,7 +130,7 @@ func (_m *MockClientInterface) CreateClientWithBody(ctx context.Context, content } } - if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -148,18 +148,18 @@ type MockClientInterface_CreateClientWithBody_Call struct { // - ctx context.Context // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) CreateClientWithBody(ctx interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_CreateClientWithBody_Call { return &MockClientInterface_CreateClientWithBody_Call{Call: _e.mock.On("CreateClientWithBody", append([]interface{}{ctx, contentType, body}, reqEditors...)...)} } -func (_c *MockClientInterface_CreateClientWithBody_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_CreateClientWithBody_Call { +func (_c *MockClientInterface_CreateClientWithBody_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_CreateClientWithBody_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(io.Reader), variadicArgs...) @@ -172,13 +172,13 @@ func (_c *MockClientInterface_CreateClientWithBody_Call) Return(_a0 *http.Respon return _c } -func (_c *MockClientInterface_CreateClientWithBody_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateClientWithBody_Call { +func (_c *MockClientInterface_CreateClientWithBody_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateClientWithBody_Call { _c.Call.Return(run) return _c } // CreateQuery provides a mock function with given fields: ctx, body, reqEditors -func (_m *MockClientInterface) CreateQuery(ctx context.Context, body queryservice.QueryCreate, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) CreateQuery(ctx context.Context, body queryapi.QueryCreate, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -194,10 +194,10 @@ func (_m *MockClientInterface) CreateQuery(ctx context.Context, body queryservic var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -205,7 +205,7 @@ func (_m *MockClientInterface) CreateQuery(ctx context.Context, body queryservic } } - if rf, ok := ret.Get(1).(func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, body, reqEditors...) } else { r1 = ret.Error(1) @@ -221,22 +221,22 @@ type MockClientInterface_CreateQuery_Call struct { // CreateQuery is a helper method to define mock.On call // - ctx context.Context -// - body queryservice.QueryCreate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.QueryCreate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) CreateQuery(ctx interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_CreateQuery_Call { return &MockClientInterface_CreateQuery_Call{Call: _e.mock.On("CreateQuery", append([]interface{}{ctx, body}, reqEditors...)...)} } -func (_c *MockClientInterface_CreateQuery_Call) Run(run func(ctx context.Context, body queryservice.QueryCreate, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_CreateQuery_Call { +func (_c *MockClientInterface_CreateQuery_Call) Run(run func(ctx context.Context, body queryapi.QueryCreate, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_CreateQuery_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(queryservice.QueryCreate), variadicArgs...) + run(args[0].(context.Context), args[1].(queryapi.QueryCreate), variadicArgs...) }) return _c } @@ -246,13 +246,13 @@ func (_c *MockClientInterface_CreateQuery_Call) Return(_a0 *http.Response, _a1 e return _c } -func (_c *MockClientInterface_CreateQuery_Call) RunAndReturn(run func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateQuery_Call { +func (_c *MockClientInterface_CreateQuery_Call) RunAndReturn(run func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateQuery_Call { _c.Call.Return(run) return _c } // CreateQueryWithBody provides a mock function with given fields: ctx, contentType, body, reqEditors -func (_m *MockClientInterface) CreateQueryWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) CreateQueryWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -268,10 +268,10 @@ func (_m *MockClientInterface) CreateQueryWithBody(ctx context.Context, contentT var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -279,7 +279,7 @@ func (_m *MockClientInterface) CreateQueryWithBody(ctx context.Context, contentT } } - if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -297,18 +297,18 @@ type MockClientInterface_CreateQueryWithBody_Call struct { // - ctx context.Context // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) CreateQueryWithBody(ctx interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_CreateQueryWithBody_Call { return &MockClientInterface_CreateQueryWithBody_Call{Call: _e.mock.On("CreateQueryWithBody", append([]interface{}{ctx, contentType, body}, reqEditors...)...)} } -func (_c *MockClientInterface_CreateQueryWithBody_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_CreateQueryWithBody_Call { +func (_c *MockClientInterface_CreateQueryWithBody_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_CreateQueryWithBody_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(io.Reader), variadicArgs...) @@ -321,13 +321,13 @@ func (_c *MockClientInterface_CreateQueryWithBody_Call) Return(_a0 *http.Respons return _c } -func (_c *MockClientInterface_CreateQueryWithBody_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateQueryWithBody_Call { +func (_c *MockClientInterface_CreateQueryWithBody_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_CreateQueryWithBody_Call { _c.Call.Return(run) return _c } // ExportState provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientInterface) ExportState(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) ExportState(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -343,10 +343,10 @@ func (_m *MockClientInterface) ExportState(ctx context.Context, id uuid.UUID, re var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { @@ -354,7 +354,7 @@ func (_m *MockClientInterface) ExportState(ctx context.Context, id uuid.UUID, re } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -371,18 +371,18 @@ type MockClientInterface_ExportState_Call struct { // ExportState is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) ExportState(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientInterface_ExportState_Call { return &MockClientInterface_ExportState_Call{Call: _e.mock.On("ExportState", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientInterface_ExportState_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_ExportState_Call { +func (_c *MockClientInterface_ExportState_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_ExportState_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), variadicArgs...) @@ -395,13 +395,13 @@ func (_c *MockClientInterface_ExportState_Call) Return(_a0 *http.Response, _a1 e return _c } -func (_c *MockClientInterface_ExportState_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_ExportState_Call { +func (_c *MockClientInterface_ExportState_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_ExportState_Call { _c.Call.Return(run) return _c } // GetClient provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientInterface) GetClient(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) GetClient(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -417,10 +417,10 @@ func (_m *MockClientInterface) GetClient(ctx context.Context, id string, reqEdit var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { @@ -428,7 +428,7 @@ func (_m *MockClientInterface) GetClient(ctx context.Context, id string, reqEdit } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -445,18 +445,18 @@ type MockClientInterface_GetClient_Call struct { // GetClient is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) GetClient(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientInterface_GetClient_Call { return &MockClientInterface_GetClient_Call{Call: _e.mock.On("GetClient", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientInterface_GetClient_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_GetClient_Call { +func (_c *MockClientInterface_GetClient_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_GetClient_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -469,13 +469,13 @@ func (_c *MockClientInterface_GetClient_Call) Return(_a0 *http.Response, _a1 err return _c } -func (_c *MockClientInterface_GetClient_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetClient_Call { +func (_c *MockClientInterface_GetClient_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetClient_Call { _c.Call.Return(run) return _c } // GetCollectorByClientId provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientInterface) GetCollectorByClientId(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) GetCollectorByClientId(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -491,10 +491,10 @@ func (_m *MockClientInterface) GetCollectorByClientId(ctx context.Context, id st var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { @@ -502,7 +502,7 @@ func (_m *MockClientInterface) GetCollectorByClientId(ctx context.Context, id st } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -519,18 +519,18 @@ type MockClientInterface_GetCollectorByClientId_Call struct { // GetCollectorByClientId is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) GetCollectorByClientId(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientInterface_GetCollectorByClientId_Call { return &MockClientInterface_GetCollectorByClientId_Call{Call: _e.mock.On("GetCollectorByClientId", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientInterface_GetCollectorByClientId_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_GetCollectorByClientId_Call { +func (_c *MockClientInterface_GetCollectorByClientId_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_GetCollectorByClientId_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -543,13 +543,87 @@ func (_c *MockClientInterface_GetCollectorByClientId_Call) Return(_a0 *http.Resp return _c } -func (_c *MockClientInterface_GetCollectorByClientId_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetCollectorByClientId_Call { +func (_c *MockClientInterface_GetCollectorByClientId_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetCollectorByClientId_Call { + _c.Call.Return(run) + return _c +} + +// GetDocument provides a mock function with given fields: ctx, id, reqEditors +func (_m *MockClientInterface) GetDocument(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { + _va := make([]interface{}, len(reqEditors)) + for _i := range reqEditors { + _va[_i] = reqEditors[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, id) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetDocument") + } + + var r0 *http.Response + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { + return rf(ctx, id, reqEditors...) + } + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) *http.Response); ok { + r0 = rf(ctx, id, reqEditors...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) error); ok { + r1 = rf(ctx, id, reqEditors...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockClientInterface_GetDocument_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDocument' +type MockClientInterface_GetDocument_Call struct { + *mock.Call +} + +// GetDocument is a helper method to define mock.On call +// - ctx context.Context +// - id uuid.UUID +// - reqEditors ...queryapi.RequestEditorFn +func (_e *MockClientInterface_Expecter) GetDocument(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientInterface_GetDocument_Call { + return &MockClientInterface_GetDocument_Call{Call: _e.mock.On("GetDocument", + append([]interface{}{ctx, id}, reqEditors...)...)} +} + +func (_c *MockClientInterface_GetDocument_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_GetDocument_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(queryapi.RequestEditorFn) + } + } + run(args[0].(context.Context), args[1].(uuid.UUID), variadicArgs...) + }) + return _c +} + +func (_c *MockClientInterface_GetDocument_Call) Return(_a0 *http.Response, _a1 error) *MockClientInterface_GetDocument_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockClientInterface_GetDocument_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetDocument_Call { _c.Call.Return(run) return _c } // GetQuery provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientInterface) GetQuery(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) GetQuery(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -565,10 +639,10 @@ func (_m *MockClientInterface) GetQuery(ctx context.Context, id uuid.UUID, reqEd var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { @@ -576,7 +650,7 @@ func (_m *MockClientInterface) GetQuery(ctx context.Context, id uuid.UUID, reqEd } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -593,18 +667,18 @@ type MockClientInterface_GetQuery_Call struct { // GetQuery is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) GetQuery(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientInterface_GetQuery_Call { return &MockClientInterface_GetQuery_Call{Call: _e.mock.On("GetQuery", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientInterface_GetQuery_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_GetQuery_Call { +func (_c *MockClientInterface_GetQuery_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_GetQuery_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), variadicArgs...) @@ -617,13 +691,13 @@ func (_c *MockClientInterface_GetQuery_Call) Return(_a0 *http.Response, _a1 erro return _c } -func (_c *MockClientInterface_GetQuery_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetQuery_Call { +func (_c *MockClientInterface_GetQuery_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetQuery_Call { _c.Call.Return(run) return _c } // GetStatusByClientId provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientInterface) GetStatusByClientId(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) GetStatusByClientId(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -639,10 +713,10 @@ func (_m *MockClientInterface) GetStatusByClientId(ctx context.Context, id strin var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { @@ -650,7 +724,7 @@ func (_m *MockClientInterface) GetStatusByClientId(ctx context.Context, id strin } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -667,18 +741,18 @@ type MockClientInterface_GetStatusByClientId_Call struct { // GetStatusByClientId is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) GetStatusByClientId(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientInterface_GetStatusByClientId_Call { return &MockClientInterface_GetStatusByClientId_Call{Call: _e.mock.On("GetStatusByClientId", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientInterface_GetStatusByClientId_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_GetStatusByClientId_Call { +func (_c *MockClientInterface_GetStatusByClientId_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_GetStatusByClientId_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -691,13 +765,13 @@ func (_c *MockClientInterface_GetStatusByClientId_Call) Return(_a0 *http.Respons return _c } -func (_c *MockClientInterface_GetStatusByClientId_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetStatusByClientId_Call { +func (_c *MockClientInterface_GetStatusByClientId_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_GetStatusByClientId_Call { _c.Call.Return(run) return _c } // ListDocumentsByClientId provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientInterface) ListDocumentsByClientId(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) ListDocumentsByClientId(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -713,10 +787,10 @@ func (_m *MockClientInterface) ListDocumentsByClientId(ctx context.Context, id s var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { @@ -724,7 +798,7 @@ func (_m *MockClientInterface) ListDocumentsByClientId(ctx context.Context, id s } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -741,18 +815,18 @@ type MockClientInterface_ListDocumentsByClientId_Call struct { // ListDocumentsByClientId is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) ListDocumentsByClientId(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientInterface_ListDocumentsByClientId_Call { return &MockClientInterface_ListDocumentsByClientId_Call{Call: _e.mock.On("ListDocumentsByClientId", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientInterface_ListDocumentsByClientId_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_ListDocumentsByClientId_Call { +func (_c *MockClientInterface_ListDocumentsByClientId_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_ListDocumentsByClientId_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -765,13 +839,13 @@ func (_c *MockClientInterface_ListDocumentsByClientId_Call) Return(_a0 *http.Res return _c } -func (_c *MockClientInterface_ListDocumentsByClientId_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_ListDocumentsByClientId_Call { +func (_c *MockClientInterface_ListDocumentsByClientId_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_ListDocumentsByClientId_Call { _c.Call.Return(run) return _c } // ListQueries provides a mock function with given fields: ctx, reqEditors -func (_m *MockClientInterface) ListQueries(ctx context.Context, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) ListQueries(ctx context.Context, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -787,10 +861,10 @@ func (_m *MockClientInterface) ListQueries(ctx context.Context, reqEditors ...qu var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, reqEditors...) } else { if ret.Get(0) != nil { @@ -798,7 +872,7 @@ func (_m *MockClientInterface) ListQueries(ctx context.Context, reqEditors ...qu } } - if rf, ok := ret.Get(1).(func(context.Context, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, reqEditors...) } else { r1 = ret.Error(1) @@ -814,18 +888,18 @@ type MockClientInterface_ListQueries_Call struct { // ListQueries is a helper method to define mock.On call // - ctx context.Context -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) ListQueries(ctx interface{}, reqEditors ...interface{}) *MockClientInterface_ListQueries_Call { return &MockClientInterface_ListQueries_Call{Call: _e.mock.On("ListQueries", append([]interface{}{ctx}, reqEditors...)...)} } -func (_c *MockClientInterface_ListQueries_Call) Run(run func(ctx context.Context, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_ListQueries_Call { +func (_c *MockClientInterface_ListQueries_Call) Run(run func(ctx context.Context, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_ListQueries_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-1) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-1) for i, a := range args[1:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), variadicArgs...) @@ -838,13 +912,13 @@ func (_c *MockClientInterface_ListQueries_Call) Return(_a0 *http.Response, _a1 e return _c } -func (_c *MockClientInterface_ListQueries_Call) RunAndReturn(run func(context.Context, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_ListQueries_Call { +func (_c *MockClientInterface_ListQueries_Call) RunAndReturn(run func(context.Context, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_ListQueries_Call { _c.Call.Return(run) return _c } // SetCollectorByClientId provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientInterface) SetCollectorByClientId(ctx context.Context, id string, body queryservice.CollectorSet, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) SetCollectorByClientId(ctx context.Context, id string, body queryapi.CollectorSet, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -860,10 +934,10 @@ func (_m *MockClientInterface) SetCollectorByClientId(ctx context.Context, id st var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -871,7 +945,7 @@ func (_m *MockClientInterface) SetCollectorByClientId(ctx context.Context, id st } } - if rf, ok := ret.Get(1).(func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -888,22 +962,22 @@ type MockClientInterface_SetCollectorByClientId_Call struct { // SetCollectorByClientId is a helper method to define mock.On call // - ctx context.Context // - id string -// - body queryservice.CollectorSet -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.CollectorSet +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) SetCollectorByClientId(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_SetCollectorByClientId_Call { return &MockClientInterface_SetCollectorByClientId_Call{Call: _e.mock.On("SetCollectorByClientId", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientInterface_SetCollectorByClientId_Call) Run(run func(ctx context.Context, id string, body queryservice.CollectorSet, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_SetCollectorByClientId_Call { +func (_c *MockClientInterface_SetCollectorByClientId_Call) Run(run func(ctx context.Context, id string, body queryapi.CollectorSet, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_SetCollectorByClientId_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(string), args[2].(queryservice.CollectorSet), variadicArgs...) + run(args[0].(context.Context), args[1].(string), args[2].(queryapi.CollectorSet), variadicArgs...) }) return _c } @@ -913,13 +987,13 @@ func (_c *MockClientInterface_SetCollectorByClientId_Call) Return(_a0 *http.Resp return _c } -func (_c *MockClientInterface_SetCollectorByClientId_Call) RunAndReturn(run func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_SetCollectorByClientId_Call { +func (_c *MockClientInterface_SetCollectorByClientId_Call) RunAndReturn(run func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_SetCollectorByClientId_Call { _c.Call.Return(run) return _c } // SetCollectorByClientIdWithBody provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientInterface) SetCollectorByClientIdWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) SetCollectorByClientIdWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -935,10 +1009,10 @@ func (_m *MockClientInterface) SetCollectorByClientIdWithBody(ctx context.Contex var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -946,7 +1020,7 @@ func (_m *MockClientInterface) SetCollectorByClientIdWithBody(ctx context.Contex } } - if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -965,18 +1039,18 @@ type MockClientInterface_SetCollectorByClientIdWithBody_Call struct { // - id string // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) SetCollectorByClientIdWithBody(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_SetCollectorByClientIdWithBody_Call { return &MockClientInterface_SetCollectorByClientIdWithBody_Call{Call: _e.mock.On("SetCollectorByClientIdWithBody", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientInterface_SetCollectorByClientIdWithBody_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_SetCollectorByClientIdWithBody_Call { +func (_c *MockClientInterface_SetCollectorByClientIdWithBody_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_SetCollectorByClientIdWithBody_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -989,13 +1063,13 @@ func (_c *MockClientInterface_SetCollectorByClientIdWithBody_Call) Return(_a0 *h return _c } -func (_c *MockClientInterface_SetCollectorByClientIdWithBody_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_SetCollectorByClientIdWithBody_Call { +func (_c *MockClientInterface_SetCollectorByClientIdWithBody_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_SetCollectorByClientIdWithBody_Call { _c.Call.Return(run) return _c } // TestQuery provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientInterface) TestQuery(ctx context.Context, id uuid.UUID, body queryservice.QueryTestRequest, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) TestQuery(ctx context.Context, id uuid.UUID, body queryapi.QueryTestRequest, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1011,10 +1085,10 @@ func (_m *MockClientInterface) TestQuery(ctx context.Context, id uuid.UUID, body var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1022,7 +1096,7 @@ func (_m *MockClientInterface) TestQuery(ctx context.Context, id uuid.UUID, body } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1039,22 +1113,22 @@ type MockClientInterface_TestQuery_Call struct { // TestQuery is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - body queryservice.QueryTestRequest -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.QueryTestRequest +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) TestQuery(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_TestQuery_Call { return &MockClientInterface_TestQuery_Call{Call: _e.mock.On("TestQuery", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientInterface_TestQuery_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryservice.QueryTestRequest, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_TestQuery_Call { +func (_c *MockClientInterface_TestQuery_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryapi.QueryTestRequest, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_TestQuery_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryservice.QueryTestRequest), variadicArgs...) + run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryapi.QueryTestRequest), variadicArgs...) }) return _c } @@ -1064,13 +1138,13 @@ func (_c *MockClientInterface_TestQuery_Call) Return(_a0 *http.Response, _a1 err return _c } -func (_c *MockClientInterface_TestQuery_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TestQuery_Call { +func (_c *MockClientInterface_TestQuery_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TestQuery_Call { _c.Call.Return(run) return _c } // TestQueryWithBody provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientInterface) TestQueryWithBody(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) TestQueryWithBody(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1086,10 +1160,10 @@ func (_m *MockClientInterface) TestQueryWithBody(ctx context.Context, id uuid.UU var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1097,7 +1171,7 @@ func (_m *MockClientInterface) TestQueryWithBody(ctx context.Context, id uuid.UU } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1116,18 +1190,18 @@ type MockClientInterface_TestQueryWithBody_Call struct { // - id uuid.UUID // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) TestQueryWithBody(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_TestQueryWithBody_Call { return &MockClientInterface_TestQueryWithBody_Call{Call: _e.mock.On("TestQueryWithBody", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientInterface_TestQueryWithBody_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_TestQueryWithBody_Call { +func (_c *MockClientInterface_TestQueryWithBody_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_TestQueryWithBody_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1140,13 +1214,13 @@ func (_c *MockClientInterface_TestQueryWithBody_Call) Return(_a0 *http.Response, return _c } -func (_c *MockClientInterface_TestQueryWithBody_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TestQueryWithBody_Call { +func (_c *MockClientInterface_TestQueryWithBody_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TestQueryWithBody_Call { _c.Call.Return(run) return _c } // TriggerExport provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientInterface) TriggerExport(ctx context.Context, id string, body queryservice.ExportTrigger, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) TriggerExport(ctx context.Context, id string, body queryapi.ExportTrigger, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1162,10 +1236,10 @@ func (_m *MockClientInterface) TriggerExport(ctx context.Context, id string, bod var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1173,7 +1247,7 @@ func (_m *MockClientInterface) TriggerExport(ctx context.Context, id string, bod } } - if rf, ok := ret.Get(1).(func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1190,22 +1264,22 @@ type MockClientInterface_TriggerExport_Call struct { // TriggerExport is a helper method to define mock.On call // - ctx context.Context // - id string -// - body queryservice.ExportTrigger -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.ExportTrigger +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) TriggerExport(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_TriggerExport_Call { return &MockClientInterface_TriggerExport_Call{Call: _e.mock.On("TriggerExport", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientInterface_TriggerExport_Call) Run(run func(ctx context.Context, id string, body queryservice.ExportTrigger, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_TriggerExport_Call { +func (_c *MockClientInterface_TriggerExport_Call) Run(run func(ctx context.Context, id string, body queryapi.ExportTrigger, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_TriggerExport_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(string), args[2].(queryservice.ExportTrigger), variadicArgs...) + run(args[0].(context.Context), args[1].(string), args[2].(queryapi.ExportTrigger), variadicArgs...) }) return _c } @@ -1215,13 +1289,13 @@ func (_c *MockClientInterface_TriggerExport_Call) Return(_a0 *http.Response, _a1 return _c } -func (_c *MockClientInterface_TriggerExport_Call) RunAndReturn(run func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TriggerExport_Call { +func (_c *MockClientInterface_TriggerExport_Call) RunAndReturn(run func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TriggerExport_Call { _c.Call.Return(run) return _c } // TriggerExportWithBody provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientInterface) TriggerExportWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) TriggerExportWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1237,10 +1311,10 @@ func (_m *MockClientInterface) TriggerExportWithBody(ctx context.Context, id str var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1248,7 +1322,7 @@ func (_m *MockClientInterface) TriggerExportWithBody(ctx context.Context, id str } } - if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1267,18 +1341,18 @@ type MockClientInterface_TriggerExportWithBody_Call struct { // - id string // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) TriggerExportWithBody(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_TriggerExportWithBody_Call { return &MockClientInterface_TriggerExportWithBody_Call{Call: _e.mock.On("TriggerExportWithBody", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientInterface_TriggerExportWithBody_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_TriggerExportWithBody_Call { +func (_c *MockClientInterface_TriggerExportWithBody_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_TriggerExportWithBody_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1291,13 +1365,13 @@ func (_c *MockClientInterface_TriggerExportWithBody_Call) Return(_a0 *http.Respo return _c } -func (_c *MockClientInterface_TriggerExportWithBody_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TriggerExportWithBody_Call { +func (_c *MockClientInterface_TriggerExportWithBody_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_TriggerExportWithBody_Call { _c.Call.Return(run) return _c } // UpdateClient provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientInterface) UpdateClient(ctx context.Context, id string, body queryservice.ClientUpdate, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) UpdateClient(ctx context.Context, id string, body queryapi.ClientUpdate, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1313,10 +1387,10 @@ func (_m *MockClientInterface) UpdateClient(ctx context.Context, id string, body var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1324,7 +1398,7 @@ func (_m *MockClientInterface) UpdateClient(ctx context.Context, id string, body } } - if rf, ok := ret.Get(1).(func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1341,22 +1415,22 @@ type MockClientInterface_UpdateClient_Call struct { // UpdateClient is a helper method to define mock.On call // - ctx context.Context // - id string -// - body queryservice.ClientUpdate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.ClientUpdate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) UpdateClient(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_UpdateClient_Call { return &MockClientInterface_UpdateClient_Call{Call: _e.mock.On("UpdateClient", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientInterface_UpdateClient_Call) Run(run func(ctx context.Context, id string, body queryservice.ClientUpdate, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_UpdateClient_Call { +func (_c *MockClientInterface_UpdateClient_Call) Run(run func(ctx context.Context, id string, body queryapi.ClientUpdate, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_UpdateClient_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(string), args[2].(queryservice.ClientUpdate), variadicArgs...) + run(args[0].(context.Context), args[1].(string), args[2].(queryapi.ClientUpdate), variadicArgs...) }) return _c } @@ -1366,13 +1440,13 @@ func (_c *MockClientInterface_UpdateClient_Call) Return(_a0 *http.Response, _a1 return _c } -func (_c *MockClientInterface_UpdateClient_Call) RunAndReturn(run func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateClient_Call { +func (_c *MockClientInterface_UpdateClient_Call) RunAndReturn(run func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateClient_Call { _c.Call.Return(run) return _c } // UpdateClientWithBody provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientInterface) UpdateClientWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) UpdateClientWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1388,10 +1462,10 @@ func (_m *MockClientInterface) UpdateClientWithBody(ctx context.Context, id stri var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1399,7 +1473,7 @@ func (_m *MockClientInterface) UpdateClientWithBody(ctx context.Context, id stri } } - if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1418,18 +1492,18 @@ type MockClientInterface_UpdateClientWithBody_Call struct { // - id string // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) UpdateClientWithBody(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_UpdateClientWithBody_Call { return &MockClientInterface_UpdateClientWithBody_Call{Call: _e.mock.On("UpdateClientWithBody", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientInterface_UpdateClientWithBody_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_UpdateClientWithBody_Call { +func (_c *MockClientInterface_UpdateClientWithBody_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_UpdateClientWithBody_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1442,13 +1516,13 @@ func (_c *MockClientInterface_UpdateClientWithBody_Call) Return(_a0 *http.Respon return _c } -func (_c *MockClientInterface_UpdateClientWithBody_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateClientWithBody_Call { +func (_c *MockClientInterface_UpdateClientWithBody_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateClientWithBody_Call { _c.Call.Return(run) return _c } // UpdateQuery provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientInterface) UpdateQuery(ctx context.Context, id uuid.UUID, body queryservice.QueryUpdate, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) UpdateQuery(ctx context.Context, id uuid.UUID, body queryapi.QueryUpdate, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1464,10 +1538,10 @@ func (_m *MockClientInterface) UpdateQuery(ctx context.Context, id uuid.UUID, bo var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1475,7 +1549,7 @@ func (_m *MockClientInterface) UpdateQuery(ctx context.Context, id uuid.UUID, bo } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1492,22 +1566,22 @@ type MockClientInterface_UpdateQuery_Call struct { // UpdateQuery is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - body queryservice.QueryUpdate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.QueryUpdate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) UpdateQuery(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_UpdateQuery_Call { return &MockClientInterface_UpdateQuery_Call{Call: _e.mock.On("UpdateQuery", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientInterface_UpdateQuery_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryservice.QueryUpdate, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_UpdateQuery_Call { +func (_c *MockClientInterface_UpdateQuery_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryapi.QueryUpdate, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_UpdateQuery_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryservice.QueryUpdate), variadicArgs...) + run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryapi.QueryUpdate), variadicArgs...) }) return _c } @@ -1517,13 +1591,13 @@ func (_c *MockClientInterface_UpdateQuery_Call) Return(_a0 *http.Response, _a1 e return _c } -func (_c *MockClientInterface_UpdateQuery_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateQuery_Call { +func (_c *MockClientInterface_UpdateQuery_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateQuery_Call { _c.Call.Return(run) return _c } // UpdateQueryWithBody provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientInterface) UpdateQueryWithBody(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*http.Response, error) { +func (_m *MockClientInterface) UpdateQueryWithBody(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*http.Response, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1539,10 +1613,10 @@ func (_m *MockClientInterface) UpdateQueryWithBody(ctx context.Context, id uuid. var r0 *http.Response var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) *http.Response); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) *http.Response); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { @@ -1550,7 +1624,7 @@ func (_m *MockClientInterface) UpdateQueryWithBody(ctx context.Context, id uuid. } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1569,18 +1643,18 @@ type MockClientInterface_UpdateQueryWithBody_Call struct { // - id uuid.UUID // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientInterface_Expecter) UpdateQueryWithBody(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientInterface_UpdateQueryWithBody_Call { return &MockClientInterface_UpdateQueryWithBody_Call{Call: _e.mock.On("UpdateQueryWithBody", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientInterface_UpdateQueryWithBody_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientInterface_UpdateQueryWithBody_Call { +func (_c *MockClientInterface_UpdateQueryWithBody_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientInterface_UpdateQueryWithBody_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1593,7 +1667,7 @@ func (_c *MockClientInterface_UpdateQueryWithBody_Call) Return(_a0 *http.Respons return _c } -func (_c *MockClientInterface_UpdateQueryWithBody_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateQueryWithBody_Call { +func (_c *MockClientInterface_UpdateQueryWithBody_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*http.Response, error)) *MockClientInterface_UpdateQueryWithBody_Call { _c.Call.Return(run) return _c } diff --git a/mocks/queryservice/mock_ClientWithResponsesInterface.go b/mocks/queryapi/mock_ClientWithResponsesInterface.go similarity index 65% rename from mocks/queryservice/mock_ClientWithResponsesInterface.go rename to mocks/queryapi/mock_ClientWithResponsesInterface.go index 524ad16e..e602fa27 100644 --- a/mocks/queryservice/mock_ClientWithResponsesInterface.go +++ b/mocks/queryapi/mock_ClientWithResponsesInterface.go @@ -1,6 +1,6 @@ // Code generated by mockery v2.52.3. DO NOT EDIT. -package queryservicemock +package queryapimock import ( context "context" @@ -8,7 +8,7 @@ import ( mock "github.com/stretchr/testify/mock" - queryservice "queryorchestration/pkg/queryService" + queryapi "queryorchestration/pkg/queryAPI" uuid "github.com/google/uuid" ) @@ -27,7 +27,7 @@ func (_m *MockClientWithResponsesInterface) EXPECT() *MockClientWithResponsesInt } // CreateClientWithBodyWithResponse provides a mock function with given fields: ctx, contentType, body, reqEditors -func (_m *MockClientWithResponsesInterface) CreateClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*queryservice.CreateClientResponse, error) { +func (_m *MockClientWithResponsesInterface) CreateClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*queryapi.CreateClientResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -41,20 +41,20 @@ func (_m *MockClientWithResponsesInterface) CreateClientWithBodyWithResponse(ctx panic("no return value specified for CreateClientWithBodyWithResponse") } - var r0 *queryservice.CreateClientResponse + var r0 *queryapi.CreateClientResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.CreateClientResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.CreateClientResponse, error)); ok { return rf(ctx, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) *queryservice.CreateClientResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) *queryapi.CreateClientResponse); ok { r0 = rf(ctx, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.CreateClientResponse) + r0 = ret.Get(0).(*queryapi.CreateClientResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -72,18 +72,18 @@ type MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call stru // - ctx context.Context // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) CreateClientWithBodyWithResponse(ctx interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call { return &MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call{Call: _e.mock.On("CreateClientWithBodyWithResponse", append([]interface{}{ctx, contentType, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(io.Reader), variadicArgs...) @@ -91,18 +91,18 @@ func (_c *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call return _c } -func (_c *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call) Return(_a0 *queryservice.CreateClientResponse, _a1 error) *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call) Return(_a0 *queryapi.CreateClientResponse, _a1 error) *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.CreateClientResponse, error)) *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.CreateClientResponse, error)) *MockClientWithResponsesInterface_CreateClientWithBodyWithResponse_Call { _c.Call.Return(run) return _c } // CreateClientWithResponse provides a mock function with given fields: ctx, body, reqEditors -func (_m *MockClientWithResponsesInterface) CreateClientWithResponse(ctx context.Context, body queryservice.ClientCreate, reqEditors ...queryservice.RequestEditorFn) (*queryservice.CreateClientResponse, error) { +func (_m *MockClientWithResponsesInterface) CreateClientWithResponse(ctx context.Context, body queryapi.ClientCreate, reqEditors ...queryapi.RequestEditorFn) (*queryapi.CreateClientResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -116,20 +116,20 @@ func (_m *MockClientWithResponsesInterface) CreateClientWithResponse(ctx context panic("no return value specified for CreateClientWithResponse") } - var r0 *queryservice.CreateClientResponse + var r0 *queryapi.CreateClientResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) (*queryservice.CreateClientResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) (*queryapi.CreateClientResponse, error)); ok { return rf(ctx, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) *queryservice.CreateClientResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) *queryapi.CreateClientResponse); ok { r0 = rf(ctx, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.CreateClientResponse) + r0 = ret.Get(0).(*queryapi.CreateClientResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, body, reqEditors...) } else { r1 = ret.Error(1) @@ -145,38 +145,38 @@ type MockClientWithResponsesInterface_CreateClientWithResponse_Call struct { // CreateClientWithResponse is a helper method to define mock.On call // - ctx context.Context -// - body queryservice.ClientCreate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.ClientCreate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) CreateClientWithResponse(ctx interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_CreateClientWithResponse_Call { return &MockClientWithResponsesInterface_CreateClientWithResponse_Call{Call: _e.mock.On("CreateClientWithResponse", append([]interface{}{ctx, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_CreateClientWithResponse_Call) Run(run func(ctx context.Context, body queryservice.ClientCreate, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_CreateClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateClientWithResponse_Call) Run(run func(ctx context.Context, body queryapi.ClientCreate, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_CreateClientWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(queryservice.ClientCreate), variadicArgs...) + run(args[0].(context.Context), args[1].(queryapi.ClientCreate), variadicArgs...) }) return _c } -func (_c *MockClientWithResponsesInterface_CreateClientWithResponse_Call) Return(_a0 *queryservice.CreateClientResponse, _a1 error) *MockClientWithResponsesInterface_CreateClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateClientWithResponse_Call) Return(_a0 *queryapi.CreateClientResponse, _a1 error) *MockClientWithResponsesInterface_CreateClientWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_CreateClientWithResponse_Call) RunAndReturn(run func(context.Context, queryservice.ClientCreate, ...queryservice.RequestEditorFn) (*queryservice.CreateClientResponse, error)) *MockClientWithResponsesInterface_CreateClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateClientWithResponse_Call) RunAndReturn(run func(context.Context, queryapi.ClientCreate, ...queryapi.RequestEditorFn) (*queryapi.CreateClientResponse, error)) *MockClientWithResponsesInterface_CreateClientWithResponse_Call { _c.Call.Return(run) return _c } // CreateQueryWithBodyWithResponse provides a mock function with given fields: ctx, contentType, body, reqEditors -func (_m *MockClientWithResponsesInterface) CreateQueryWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*queryservice.CreateQueryResponse, error) { +func (_m *MockClientWithResponsesInterface) CreateQueryWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*queryapi.CreateQueryResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -190,20 +190,20 @@ func (_m *MockClientWithResponsesInterface) CreateQueryWithBodyWithResponse(ctx panic("no return value specified for CreateQueryWithBodyWithResponse") } - var r0 *queryservice.CreateQueryResponse + var r0 *queryapi.CreateQueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.CreateQueryResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.CreateQueryResponse, error)); ok { return rf(ctx, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) *queryservice.CreateQueryResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) *queryapi.CreateQueryResponse); ok { r0 = rf(ctx, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.CreateQueryResponse) + r0 = ret.Get(0).(*queryapi.CreateQueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -221,18 +221,18 @@ type MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call struc // - ctx context.Context // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) CreateQueryWithBodyWithResponse(ctx interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call { return &MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call{Call: _e.mock.On("CreateQueryWithBodyWithResponse", append([]interface{}{ctx, contentType, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call) Run(run func(ctx context.Context, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(io.Reader), variadicArgs...) @@ -240,18 +240,18 @@ func (_c *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call) return _c } -func (_c *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call) Return(_a0 *queryservice.CreateQueryResponse, _a1 error) *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call) Return(_a0 *queryapi.CreateQueryResponse, _a1 error) *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.CreateQueryResponse, error)) *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.CreateQueryResponse, error)) *MockClientWithResponsesInterface_CreateQueryWithBodyWithResponse_Call { _c.Call.Return(run) return _c } // CreateQueryWithResponse provides a mock function with given fields: ctx, body, reqEditors -func (_m *MockClientWithResponsesInterface) CreateQueryWithResponse(ctx context.Context, body queryservice.QueryCreate, reqEditors ...queryservice.RequestEditorFn) (*queryservice.CreateQueryResponse, error) { +func (_m *MockClientWithResponsesInterface) CreateQueryWithResponse(ctx context.Context, body queryapi.QueryCreate, reqEditors ...queryapi.RequestEditorFn) (*queryapi.CreateQueryResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -265,20 +265,20 @@ func (_m *MockClientWithResponsesInterface) CreateQueryWithResponse(ctx context. panic("no return value specified for CreateQueryWithResponse") } - var r0 *queryservice.CreateQueryResponse + var r0 *queryapi.CreateQueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) (*queryservice.CreateQueryResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) (*queryapi.CreateQueryResponse, error)); ok { return rf(ctx, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) *queryservice.CreateQueryResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) *queryapi.CreateQueryResponse); ok { r0 = rf(ctx, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.CreateQueryResponse) + r0 = ret.Get(0).(*queryapi.CreateQueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, body, reqEditors...) } else { r1 = ret.Error(1) @@ -294,38 +294,38 @@ type MockClientWithResponsesInterface_CreateQueryWithResponse_Call struct { // CreateQueryWithResponse is a helper method to define mock.On call // - ctx context.Context -// - body queryservice.QueryCreate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.QueryCreate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) CreateQueryWithResponse(ctx interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_CreateQueryWithResponse_Call { return &MockClientWithResponsesInterface_CreateQueryWithResponse_Call{Call: _e.mock.On("CreateQueryWithResponse", append([]interface{}{ctx, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_CreateQueryWithResponse_Call) Run(run func(ctx context.Context, body queryservice.QueryCreate, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_CreateQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateQueryWithResponse_Call) Run(run func(ctx context.Context, body queryapi.QueryCreate, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_CreateQueryWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(queryservice.QueryCreate), variadicArgs...) + run(args[0].(context.Context), args[1].(queryapi.QueryCreate), variadicArgs...) }) return _c } -func (_c *MockClientWithResponsesInterface_CreateQueryWithResponse_Call) Return(_a0 *queryservice.CreateQueryResponse, _a1 error) *MockClientWithResponsesInterface_CreateQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateQueryWithResponse_Call) Return(_a0 *queryapi.CreateQueryResponse, _a1 error) *MockClientWithResponsesInterface_CreateQueryWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_CreateQueryWithResponse_Call) RunAndReturn(run func(context.Context, queryservice.QueryCreate, ...queryservice.RequestEditorFn) (*queryservice.CreateQueryResponse, error)) *MockClientWithResponsesInterface_CreateQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_CreateQueryWithResponse_Call) RunAndReturn(run func(context.Context, queryapi.QueryCreate, ...queryapi.RequestEditorFn) (*queryapi.CreateQueryResponse, error)) *MockClientWithResponsesInterface_CreateQueryWithResponse_Call { _c.Call.Return(run) return _c } // ExportStateWithResponse provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientWithResponsesInterface) ExportStateWithResponse(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn) (*queryservice.ExportStateResponse, error) { +func (_m *MockClientWithResponsesInterface) ExportStateWithResponse(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn) (*queryapi.ExportStateResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -339,20 +339,20 @@ func (_m *MockClientWithResponsesInterface) ExportStateWithResponse(ctx context. panic("no return value specified for ExportStateWithResponse") } - var r0 *queryservice.ExportStateResponse + var r0 *queryapi.ExportStateResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*queryservice.ExportStateResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*queryapi.ExportStateResponse, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) *queryservice.ExportStateResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) *queryapi.ExportStateResponse); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.ExportStateResponse) + r0 = ret.Get(0).(*queryapi.ExportStateResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -369,18 +369,18 @@ type MockClientWithResponsesInterface_ExportStateWithResponse_Call struct { // ExportStateWithResponse is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) ExportStateWithResponse(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_ExportStateWithResponse_Call { return &MockClientWithResponsesInterface_ExportStateWithResponse_Call{Call: _e.mock.On("ExportStateWithResponse", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_ExportStateWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_ExportStateWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ExportStateWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_ExportStateWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), variadicArgs...) @@ -388,18 +388,18 @@ func (_c *MockClientWithResponsesInterface_ExportStateWithResponse_Call) Run(run return _c } -func (_c *MockClientWithResponsesInterface_ExportStateWithResponse_Call) Return(_a0 *queryservice.ExportStateResponse, _a1 error) *MockClientWithResponsesInterface_ExportStateWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ExportStateWithResponse_Call) Return(_a0 *queryapi.ExportStateResponse, _a1 error) *MockClientWithResponsesInterface_ExportStateWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_ExportStateWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*queryservice.ExportStateResponse, error)) *MockClientWithResponsesInterface_ExportStateWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ExportStateWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*queryapi.ExportStateResponse, error)) *MockClientWithResponsesInterface_ExportStateWithResponse_Call { _c.Call.Return(run) return _c } // GetClientWithResponse provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientWithResponsesInterface) GetClientWithResponse(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*queryservice.GetClientResponse, error) { +func (_m *MockClientWithResponsesInterface) GetClientWithResponse(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*queryapi.GetClientResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -413,20 +413,20 @@ func (_m *MockClientWithResponsesInterface) GetClientWithResponse(ctx context.Co panic("no return value specified for GetClientWithResponse") } - var r0 *queryservice.GetClientResponse + var r0 *queryapi.GetClientResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.GetClientResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.GetClientResponse, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *queryservice.GetClientResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *queryapi.GetClientResponse); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.GetClientResponse) + r0 = ret.Get(0).(*queryapi.GetClientResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -443,18 +443,18 @@ type MockClientWithResponsesInterface_GetClientWithResponse_Call struct { // GetClientWithResponse is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) GetClientWithResponse(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_GetClientWithResponse_Call { return &MockClientWithResponsesInterface_GetClientWithResponse_Call{Call: _e.mock.On("GetClientWithResponse", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_GetClientWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_GetClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetClientWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_GetClientWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -462,18 +462,18 @@ func (_c *MockClientWithResponsesInterface_GetClientWithResponse_Call) Run(run f return _c } -func (_c *MockClientWithResponsesInterface_GetClientWithResponse_Call) Return(_a0 *queryservice.GetClientResponse, _a1 error) *MockClientWithResponsesInterface_GetClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetClientWithResponse_Call) Return(_a0 *queryapi.GetClientResponse, _a1 error) *MockClientWithResponsesInterface_GetClientWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_GetClientWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.GetClientResponse, error)) *MockClientWithResponsesInterface_GetClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetClientWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.GetClientResponse, error)) *MockClientWithResponsesInterface_GetClientWithResponse_Call { _c.Call.Return(run) return _c } // GetCollectorByClientIdWithResponse provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientWithResponsesInterface) GetCollectorByClientIdWithResponse(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*queryservice.GetCollectorByClientIdResponse, error) { +func (_m *MockClientWithResponsesInterface) GetCollectorByClientIdWithResponse(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*queryapi.GetCollectorByClientIdResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -487,20 +487,20 @@ func (_m *MockClientWithResponsesInterface) GetCollectorByClientIdWithResponse(c panic("no return value specified for GetCollectorByClientIdWithResponse") } - var r0 *queryservice.GetCollectorByClientIdResponse + var r0 *queryapi.GetCollectorByClientIdResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.GetCollectorByClientIdResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.GetCollectorByClientIdResponse, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *queryservice.GetCollectorByClientIdResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *queryapi.GetCollectorByClientIdResponse); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.GetCollectorByClientIdResponse) + r0 = ret.Get(0).(*queryapi.GetCollectorByClientIdResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -517,18 +517,18 @@ type MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call st // GetCollectorByClientIdWithResponse is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) GetCollectorByClientIdWithResponse(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call { return &MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call{Call: _e.mock.On("GetCollectorByClientIdWithResponse", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -536,18 +536,92 @@ func (_c *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Ca return _c } -func (_c *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call) Return(_a0 *queryservice.GetCollectorByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call) Return(_a0 *queryapi.GetCollectorByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.GetCollectorByClientIdResponse, error)) *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.GetCollectorByClientIdResponse, error)) *MockClientWithResponsesInterface_GetCollectorByClientIdWithResponse_Call { + _c.Call.Return(run) + return _c +} + +// GetDocumentWithResponse provides a mock function with given fields: ctx, id, reqEditors +func (_m *MockClientWithResponsesInterface) GetDocumentWithResponse(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn) (*queryapi.GetDocumentResponse, error) { + _va := make([]interface{}, len(reqEditors)) + for _i := range reqEditors { + _va[_i] = reqEditors[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, id) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetDocumentWithResponse") + } + + var r0 *queryapi.GetDocumentResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*queryapi.GetDocumentResponse, error)); ok { + return rf(ctx, id, reqEditors...) + } + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) *queryapi.GetDocumentResponse); ok { + r0 = rf(ctx, id, reqEditors...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*queryapi.GetDocumentResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) error); ok { + r1 = rf(ctx, id, reqEditors...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockClientWithResponsesInterface_GetDocumentWithResponse_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDocumentWithResponse' +type MockClientWithResponsesInterface_GetDocumentWithResponse_Call struct { + *mock.Call +} + +// GetDocumentWithResponse is a helper method to define mock.On call +// - ctx context.Context +// - id uuid.UUID +// - reqEditors ...queryapi.RequestEditorFn +func (_e *MockClientWithResponsesInterface_Expecter) GetDocumentWithResponse(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_GetDocumentWithResponse_Call { + return &MockClientWithResponsesInterface_GetDocumentWithResponse_Call{Call: _e.mock.On("GetDocumentWithResponse", + append([]interface{}{ctx, id}, reqEditors...)...)} +} + +func (_c *MockClientWithResponsesInterface_GetDocumentWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_GetDocumentWithResponse_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(queryapi.RequestEditorFn) + } + } + run(args[0].(context.Context), args[1].(uuid.UUID), variadicArgs...) + }) + return _c +} + +func (_c *MockClientWithResponsesInterface_GetDocumentWithResponse_Call) Return(_a0 *queryapi.GetDocumentResponse, _a1 error) *MockClientWithResponsesInterface_GetDocumentWithResponse_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockClientWithResponsesInterface_GetDocumentWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*queryapi.GetDocumentResponse, error)) *MockClientWithResponsesInterface_GetDocumentWithResponse_Call { _c.Call.Return(run) return _c } // GetQueryWithResponse provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientWithResponsesInterface) GetQueryWithResponse(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn) (*queryservice.GetQueryResponse, error) { +func (_m *MockClientWithResponsesInterface) GetQueryWithResponse(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn) (*queryapi.GetQueryResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -561,20 +635,20 @@ func (_m *MockClientWithResponsesInterface) GetQueryWithResponse(ctx context.Con panic("no return value specified for GetQueryWithResponse") } - var r0 *queryservice.GetQueryResponse + var r0 *queryapi.GetQueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*queryservice.GetQueryResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*queryapi.GetQueryResponse, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) *queryservice.GetQueryResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) *queryapi.GetQueryResponse); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.GetQueryResponse) + r0 = ret.Get(0).(*queryapi.GetQueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -591,18 +665,18 @@ type MockClientWithResponsesInterface_GetQueryWithResponse_Call struct { // GetQueryWithResponse is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) GetQueryWithResponse(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_GetQueryWithResponse_Call { return &MockClientWithResponsesInterface_GetQueryWithResponse_Call{Call: _e.mock.On("GetQueryWithResponse", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_GetQueryWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_GetQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetQueryWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_GetQueryWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), variadicArgs...) @@ -610,18 +684,18 @@ func (_c *MockClientWithResponsesInterface_GetQueryWithResponse_Call) Run(run fu return _c } -func (_c *MockClientWithResponsesInterface_GetQueryWithResponse_Call) Return(_a0 *queryservice.GetQueryResponse, _a1 error) *MockClientWithResponsesInterface_GetQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetQueryWithResponse_Call) Return(_a0 *queryapi.GetQueryResponse, _a1 error) *MockClientWithResponsesInterface_GetQueryWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_GetQueryWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryservice.RequestEditorFn) (*queryservice.GetQueryResponse, error)) *MockClientWithResponsesInterface_GetQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetQueryWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, ...queryapi.RequestEditorFn) (*queryapi.GetQueryResponse, error)) *MockClientWithResponsesInterface_GetQueryWithResponse_Call { _c.Call.Return(run) return _c } // GetStatusByClientIdWithResponse provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientWithResponsesInterface) GetStatusByClientIdWithResponse(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*queryservice.GetStatusByClientIdResponse, error) { +func (_m *MockClientWithResponsesInterface) GetStatusByClientIdWithResponse(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*queryapi.GetStatusByClientIdResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -635,20 +709,20 @@ func (_m *MockClientWithResponsesInterface) GetStatusByClientIdWithResponse(ctx panic("no return value specified for GetStatusByClientIdWithResponse") } - var r0 *queryservice.GetStatusByClientIdResponse + var r0 *queryapi.GetStatusByClientIdResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.GetStatusByClientIdResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.GetStatusByClientIdResponse, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *queryservice.GetStatusByClientIdResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *queryapi.GetStatusByClientIdResponse); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.GetStatusByClientIdResponse) + r0 = ret.Get(0).(*queryapi.GetStatusByClientIdResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -665,18 +739,18 @@ type MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call struc // GetStatusByClientIdWithResponse is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) GetStatusByClientIdWithResponse(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call { return &MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call{Call: _e.mock.On("GetStatusByClientIdWithResponse", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -684,18 +758,18 @@ func (_c *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call) return _c } -func (_c *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call) Return(_a0 *queryservice.GetStatusByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call) Return(_a0 *queryapi.GetStatusByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.GetStatusByClientIdResponse, error)) *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.GetStatusByClientIdResponse, error)) *MockClientWithResponsesInterface_GetStatusByClientIdWithResponse_Call { _c.Call.Return(run) return _c } // ListDocumentsByClientIdWithResponse provides a mock function with given fields: ctx, id, reqEditors -func (_m *MockClientWithResponsesInterface) ListDocumentsByClientIdWithResponse(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn) (*queryservice.ListDocumentsByClientIdResponse, error) { +func (_m *MockClientWithResponsesInterface) ListDocumentsByClientIdWithResponse(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn) (*queryapi.ListDocumentsByClientIdResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -709,20 +783,20 @@ func (_m *MockClientWithResponsesInterface) ListDocumentsByClientIdWithResponse( panic("no return value specified for ListDocumentsByClientIdWithResponse") } - var r0 *queryservice.ListDocumentsByClientIdResponse + var r0 *queryapi.ListDocumentsByClientIdResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.ListDocumentsByClientIdResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.ListDocumentsByClientIdResponse, error)); ok { return rf(ctx, id, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...queryservice.RequestEditorFn) *queryservice.ListDocumentsByClientIdResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, ...queryapi.RequestEditorFn) *queryapi.ListDocumentsByClientIdResponse); ok { r0 = rf(ctx, id, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.ListDocumentsByClientIdResponse) + r0 = ret.Get(0).(*queryapi.ListDocumentsByClientIdResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, reqEditors...) } else { r1 = ret.Error(1) @@ -739,18 +813,18 @@ type MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call s // ListDocumentsByClientIdWithResponse is a helper method to define mock.On call // - ctx context.Context // - id string -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) ListDocumentsByClientIdWithResponse(ctx interface{}, id interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call { return &MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call{Call: _e.mock.On("ListDocumentsByClientIdWithResponse", append([]interface{}{ctx, id}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-2) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-2) for i, a := range args[2:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), variadicArgs...) @@ -758,18 +832,18 @@ func (_c *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_C return _c } -func (_c *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call) Return(_a0 *queryservice.ListDocumentsByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call) Return(_a0 *queryapi.ListDocumentsByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryservice.RequestEditorFn) (*queryservice.ListDocumentsByClientIdResponse, error)) *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, ...queryapi.RequestEditorFn) (*queryapi.ListDocumentsByClientIdResponse, error)) *MockClientWithResponsesInterface_ListDocumentsByClientIdWithResponse_Call { _c.Call.Return(run) return _c } // ListQueriesWithResponse provides a mock function with given fields: ctx, reqEditors -func (_m *MockClientWithResponsesInterface) ListQueriesWithResponse(ctx context.Context, reqEditors ...queryservice.RequestEditorFn) (*queryservice.ListQueriesResponse, error) { +func (_m *MockClientWithResponsesInterface) ListQueriesWithResponse(ctx context.Context, reqEditors ...queryapi.RequestEditorFn) (*queryapi.ListQueriesResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -783,20 +857,20 @@ func (_m *MockClientWithResponsesInterface) ListQueriesWithResponse(ctx context. panic("no return value specified for ListQueriesWithResponse") } - var r0 *queryservice.ListQueriesResponse + var r0 *queryapi.ListQueriesResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ...queryservice.RequestEditorFn) (*queryservice.ListQueriesResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, ...queryapi.RequestEditorFn) (*queryapi.ListQueriesResponse, error)); ok { return rf(ctx, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, ...queryservice.RequestEditorFn) *queryservice.ListQueriesResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, ...queryapi.RequestEditorFn) *queryapi.ListQueriesResponse); ok { r0 = rf(ctx, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.ListQueriesResponse) + r0 = ret.Get(0).(*queryapi.ListQueriesResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, reqEditors...) } else { r1 = ret.Error(1) @@ -812,18 +886,18 @@ type MockClientWithResponsesInterface_ListQueriesWithResponse_Call struct { // ListQueriesWithResponse is a helper method to define mock.On call // - ctx context.Context -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) ListQueriesWithResponse(ctx interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_ListQueriesWithResponse_Call { return &MockClientWithResponsesInterface_ListQueriesWithResponse_Call{Call: _e.mock.On("ListQueriesWithResponse", append([]interface{}{ctx}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_ListQueriesWithResponse_Call) Run(run func(ctx context.Context, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_ListQueriesWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ListQueriesWithResponse_Call) Run(run func(ctx context.Context, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_ListQueriesWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-1) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-1) for i, a := range args[1:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), variadicArgs...) @@ -831,18 +905,18 @@ func (_c *MockClientWithResponsesInterface_ListQueriesWithResponse_Call) Run(run return _c } -func (_c *MockClientWithResponsesInterface_ListQueriesWithResponse_Call) Return(_a0 *queryservice.ListQueriesResponse, _a1 error) *MockClientWithResponsesInterface_ListQueriesWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ListQueriesWithResponse_Call) Return(_a0 *queryapi.ListQueriesResponse, _a1 error) *MockClientWithResponsesInterface_ListQueriesWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_ListQueriesWithResponse_Call) RunAndReturn(run func(context.Context, ...queryservice.RequestEditorFn) (*queryservice.ListQueriesResponse, error)) *MockClientWithResponsesInterface_ListQueriesWithResponse_Call { +func (_c *MockClientWithResponsesInterface_ListQueriesWithResponse_Call) RunAndReturn(run func(context.Context, ...queryapi.RequestEditorFn) (*queryapi.ListQueriesResponse, error)) *MockClientWithResponsesInterface_ListQueriesWithResponse_Call { _c.Call.Return(run) return _c } // SetCollectorByClientIdWithBodyWithResponse provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientWithResponsesInterface) SetCollectorByClientIdWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*queryservice.SetCollectorByClientIdResponse, error) { +func (_m *MockClientWithResponsesInterface) SetCollectorByClientIdWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*queryapi.SetCollectorByClientIdResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -856,20 +930,20 @@ func (_m *MockClientWithResponsesInterface) SetCollectorByClientIdWithBodyWithRe panic("no return value specified for SetCollectorByClientIdWithBodyWithResponse") } - var r0 *queryservice.SetCollectorByClientIdResponse + var r0 *queryapi.SetCollectorByClientIdResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.SetCollectorByClientIdResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.SetCollectorByClientIdResponse, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) *queryservice.SetCollectorByClientIdResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) *queryapi.SetCollectorByClientIdResponse); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.SetCollectorByClientIdResponse) + r0 = ret.Get(0).(*queryapi.SetCollectorByClientIdResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -888,18 +962,18 @@ type MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse // - id string // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) SetCollectorByClientIdWithBodyWithResponse(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call { return &MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call{Call: _e.mock.On("SetCollectorByClientIdWithBodyWithResponse", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -907,18 +981,18 @@ func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithRes return _c } -func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call) Return(_a0 *queryservice.SetCollectorByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call) Return(_a0 *queryapi.SetCollectorByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.SetCollectorByClientIdResponse, error)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.SetCollectorByClientIdResponse, error)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithBodyWithResponse_Call { _c.Call.Return(run) return _c } // SetCollectorByClientIdWithResponse provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientWithResponsesInterface) SetCollectorByClientIdWithResponse(ctx context.Context, id string, body queryservice.CollectorSet, reqEditors ...queryservice.RequestEditorFn) (*queryservice.SetCollectorByClientIdResponse, error) { +func (_m *MockClientWithResponsesInterface) SetCollectorByClientIdWithResponse(ctx context.Context, id string, body queryapi.CollectorSet, reqEditors ...queryapi.RequestEditorFn) (*queryapi.SetCollectorByClientIdResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -932,20 +1006,20 @@ func (_m *MockClientWithResponsesInterface) SetCollectorByClientIdWithResponse(c panic("no return value specified for SetCollectorByClientIdWithResponse") } - var r0 *queryservice.SetCollectorByClientIdResponse + var r0 *queryapi.SetCollectorByClientIdResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) (*queryservice.SetCollectorByClientIdResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) (*queryapi.SetCollectorByClientIdResponse, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) *queryservice.SetCollectorByClientIdResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) *queryapi.SetCollectorByClientIdResponse); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.SetCollectorByClientIdResponse) + r0 = ret.Get(0).(*queryapi.SetCollectorByClientIdResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -962,38 +1036,38 @@ type MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call st // SetCollectorByClientIdWithResponse is a helper method to define mock.On call // - ctx context.Context // - id string -// - body queryservice.CollectorSet -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.CollectorSet +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) SetCollectorByClientIdWithResponse(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call { return &MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call{Call: _e.mock.On("SetCollectorByClientIdWithResponse", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, body queryservice.CollectorSet, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call) Run(run func(ctx context.Context, id string, body queryapi.CollectorSet, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(string), args[2].(queryservice.CollectorSet), variadicArgs...) + run(args[0].(context.Context), args[1].(string), args[2].(queryapi.CollectorSet), variadicArgs...) }) return _c } -func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call) Return(_a0 *queryservice.SetCollectorByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call) Return(_a0 *queryapi.SetCollectorByClientIdResponse, _a1 error) *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, queryservice.CollectorSet, ...queryservice.RequestEditorFn) (*queryservice.SetCollectorByClientIdResponse, error)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call { +func (_c *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call) RunAndReturn(run func(context.Context, string, queryapi.CollectorSet, ...queryapi.RequestEditorFn) (*queryapi.SetCollectorByClientIdResponse, error)) *MockClientWithResponsesInterface_SetCollectorByClientIdWithResponse_Call { _c.Call.Return(run) return _c } // TestQueryWithBodyWithResponse provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientWithResponsesInterface) TestQueryWithBodyWithResponse(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*queryservice.TestQueryResponse, error) { +func (_m *MockClientWithResponsesInterface) TestQueryWithBodyWithResponse(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*queryapi.TestQueryResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1007,20 +1081,20 @@ func (_m *MockClientWithResponsesInterface) TestQueryWithBodyWithResponse(ctx co panic("no return value specified for TestQueryWithBodyWithResponse") } - var r0 *queryservice.TestQueryResponse + var r0 *queryapi.TestQueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.TestQueryResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.TestQueryResponse, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) *queryservice.TestQueryResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) *queryapi.TestQueryResponse); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.TestQueryResponse) + r0 = ret.Get(0).(*queryapi.TestQueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1039,18 +1113,18 @@ type MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call struct // - id uuid.UUID // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) TestQueryWithBodyWithResponse(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call { return &MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call{Call: _e.mock.On("TestQueryWithBodyWithResponse", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1058,18 +1132,18 @@ func (_c *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call) R return _c } -func (_c *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call) Return(_a0 *queryservice.TestQueryResponse, _a1 error) *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call) Return(_a0 *queryapi.TestQueryResponse, _a1 error) *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.TestQueryResponse, error)) *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.TestQueryResponse, error)) *MockClientWithResponsesInterface_TestQueryWithBodyWithResponse_Call { _c.Call.Return(run) return _c } // TestQueryWithResponse provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientWithResponsesInterface) TestQueryWithResponse(ctx context.Context, id uuid.UUID, body queryservice.QueryTestRequest, reqEditors ...queryservice.RequestEditorFn) (*queryservice.TestQueryResponse, error) { +func (_m *MockClientWithResponsesInterface) TestQueryWithResponse(ctx context.Context, id uuid.UUID, body queryapi.QueryTestRequest, reqEditors ...queryapi.RequestEditorFn) (*queryapi.TestQueryResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1083,20 +1157,20 @@ func (_m *MockClientWithResponsesInterface) TestQueryWithResponse(ctx context.Co panic("no return value specified for TestQueryWithResponse") } - var r0 *queryservice.TestQueryResponse + var r0 *queryapi.TestQueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) (*queryservice.TestQueryResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) (*queryapi.TestQueryResponse, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) *queryservice.TestQueryResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) *queryapi.TestQueryResponse); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.TestQueryResponse) + r0 = ret.Get(0).(*queryapi.TestQueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1113,38 +1187,38 @@ type MockClientWithResponsesInterface_TestQueryWithResponse_Call struct { // TestQueryWithResponse is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - body queryservice.QueryTestRequest -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.QueryTestRequest +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) TestQueryWithResponse(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_TestQueryWithResponse_Call { return &MockClientWithResponsesInterface_TestQueryWithResponse_Call{Call: _e.mock.On("TestQueryWithResponse", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_TestQueryWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryservice.QueryTestRequest, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_TestQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TestQueryWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryapi.QueryTestRequest, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_TestQueryWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryservice.QueryTestRequest), variadicArgs...) + run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryapi.QueryTestRequest), variadicArgs...) }) return _c } -func (_c *MockClientWithResponsesInterface_TestQueryWithResponse_Call) Return(_a0 *queryservice.TestQueryResponse, _a1 error) *MockClientWithResponsesInterface_TestQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TestQueryWithResponse_Call) Return(_a0 *queryapi.TestQueryResponse, _a1 error) *MockClientWithResponsesInterface_TestQueryWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_TestQueryWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryservice.QueryTestRequest, ...queryservice.RequestEditorFn) (*queryservice.TestQueryResponse, error)) *MockClientWithResponsesInterface_TestQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TestQueryWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryapi.QueryTestRequest, ...queryapi.RequestEditorFn) (*queryapi.TestQueryResponse, error)) *MockClientWithResponsesInterface_TestQueryWithResponse_Call { _c.Call.Return(run) return _c } // TriggerExportWithBodyWithResponse provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientWithResponsesInterface) TriggerExportWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*queryservice.TriggerExportResponse, error) { +func (_m *MockClientWithResponsesInterface) TriggerExportWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*queryapi.TriggerExportResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1158,20 +1232,20 @@ func (_m *MockClientWithResponsesInterface) TriggerExportWithBodyWithResponse(ct panic("no return value specified for TriggerExportWithBodyWithResponse") } - var r0 *queryservice.TriggerExportResponse + var r0 *queryapi.TriggerExportResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.TriggerExportResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.TriggerExportResponse, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) *queryservice.TriggerExportResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) *queryapi.TriggerExportResponse); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.TriggerExportResponse) + r0 = ret.Get(0).(*queryapi.TriggerExportResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1190,18 +1264,18 @@ type MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call str // - id string // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) TriggerExportWithBodyWithResponse(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call { return &MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call{Call: _e.mock.On("TriggerExportWithBodyWithResponse", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1209,18 +1283,18 @@ func (_c *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Cal return _c } -func (_c *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call) Return(_a0 *queryservice.TriggerExportResponse, _a1 error) *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call) Return(_a0 *queryapi.TriggerExportResponse, _a1 error) *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.TriggerExportResponse, error)) *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.TriggerExportResponse, error)) *MockClientWithResponsesInterface_TriggerExportWithBodyWithResponse_Call { _c.Call.Return(run) return _c } // TriggerExportWithResponse provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientWithResponsesInterface) TriggerExportWithResponse(ctx context.Context, id string, body queryservice.ExportTrigger, reqEditors ...queryservice.RequestEditorFn) (*queryservice.TriggerExportResponse, error) { +func (_m *MockClientWithResponsesInterface) TriggerExportWithResponse(ctx context.Context, id string, body queryapi.ExportTrigger, reqEditors ...queryapi.RequestEditorFn) (*queryapi.TriggerExportResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1234,20 +1308,20 @@ func (_m *MockClientWithResponsesInterface) TriggerExportWithResponse(ctx contex panic("no return value specified for TriggerExportWithResponse") } - var r0 *queryservice.TriggerExportResponse + var r0 *queryapi.TriggerExportResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) (*queryservice.TriggerExportResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) (*queryapi.TriggerExportResponse, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) *queryservice.TriggerExportResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) *queryapi.TriggerExportResponse); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.TriggerExportResponse) + r0 = ret.Get(0).(*queryapi.TriggerExportResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1264,38 +1338,38 @@ type MockClientWithResponsesInterface_TriggerExportWithResponse_Call struct { // TriggerExportWithResponse is a helper method to define mock.On call // - ctx context.Context // - id string -// - body queryservice.ExportTrigger -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.ExportTrigger +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) TriggerExportWithResponse(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_TriggerExportWithResponse_Call { return &MockClientWithResponsesInterface_TriggerExportWithResponse_Call{Call: _e.mock.On("TriggerExportWithResponse", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_TriggerExportWithResponse_Call) Run(run func(ctx context.Context, id string, body queryservice.ExportTrigger, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_TriggerExportWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TriggerExportWithResponse_Call) Run(run func(ctx context.Context, id string, body queryapi.ExportTrigger, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_TriggerExportWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(string), args[2].(queryservice.ExportTrigger), variadicArgs...) + run(args[0].(context.Context), args[1].(string), args[2].(queryapi.ExportTrigger), variadicArgs...) }) return _c } -func (_c *MockClientWithResponsesInterface_TriggerExportWithResponse_Call) Return(_a0 *queryservice.TriggerExportResponse, _a1 error) *MockClientWithResponsesInterface_TriggerExportWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TriggerExportWithResponse_Call) Return(_a0 *queryapi.TriggerExportResponse, _a1 error) *MockClientWithResponsesInterface_TriggerExportWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_TriggerExportWithResponse_Call) RunAndReturn(run func(context.Context, string, queryservice.ExportTrigger, ...queryservice.RequestEditorFn) (*queryservice.TriggerExportResponse, error)) *MockClientWithResponsesInterface_TriggerExportWithResponse_Call { +func (_c *MockClientWithResponsesInterface_TriggerExportWithResponse_Call) RunAndReturn(run func(context.Context, string, queryapi.ExportTrigger, ...queryapi.RequestEditorFn) (*queryapi.TriggerExportResponse, error)) *MockClientWithResponsesInterface_TriggerExportWithResponse_Call { _c.Call.Return(run) return _c } // UpdateClientWithBodyWithResponse provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientWithResponsesInterface) UpdateClientWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*queryservice.UpdateClientResponse, error) { +func (_m *MockClientWithResponsesInterface) UpdateClientWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*queryapi.UpdateClientResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1309,20 +1383,20 @@ func (_m *MockClientWithResponsesInterface) UpdateClientWithBodyWithResponse(ctx panic("no return value specified for UpdateClientWithBodyWithResponse") } - var r0 *queryservice.UpdateClientResponse + var r0 *queryapi.UpdateClientResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.UpdateClientResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.UpdateClientResponse, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) *queryservice.UpdateClientResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) *queryapi.UpdateClientResponse); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.UpdateClientResponse) + r0 = ret.Get(0).(*queryapi.UpdateClientResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1341,18 +1415,18 @@ type MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call stru // - id string // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) UpdateClientWithBodyWithResponse(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call { return &MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call{Call: _e.mock.On("UpdateClientWithBodyWithResponse", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call) Run(run func(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1360,18 +1434,18 @@ func (_c *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call return _c } -func (_c *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call) Return(_a0 *queryservice.UpdateClientResponse, _a1 error) *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call) Return(_a0 *queryapi.UpdateClientResponse, _a1 error) *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.UpdateClientResponse, error)) *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, string, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.UpdateClientResponse, error)) *MockClientWithResponsesInterface_UpdateClientWithBodyWithResponse_Call { _c.Call.Return(run) return _c } // UpdateClientWithResponse provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientWithResponsesInterface) UpdateClientWithResponse(ctx context.Context, id string, body queryservice.ClientUpdate, reqEditors ...queryservice.RequestEditorFn) (*queryservice.UpdateClientResponse, error) { +func (_m *MockClientWithResponsesInterface) UpdateClientWithResponse(ctx context.Context, id string, body queryapi.ClientUpdate, reqEditors ...queryapi.RequestEditorFn) (*queryapi.UpdateClientResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1385,20 +1459,20 @@ func (_m *MockClientWithResponsesInterface) UpdateClientWithResponse(ctx context panic("no return value specified for UpdateClientWithResponse") } - var r0 *queryservice.UpdateClientResponse + var r0 *queryapi.UpdateClientResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) (*queryservice.UpdateClientResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) (*queryapi.UpdateClientResponse, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) *queryservice.UpdateClientResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) *queryapi.UpdateClientResponse); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.UpdateClientResponse) + r0 = ret.Get(0).(*queryapi.UpdateClientResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1415,38 +1489,38 @@ type MockClientWithResponsesInterface_UpdateClientWithResponse_Call struct { // UpdateClientWithResponse is a helper method to define mock.On call // - ctx context.Context // - id string -// - body queryservice.ClientUpdate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.ClientUpdate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) UpdateClientWithResponse(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_UpdateClientWithResponse_Call { return &MockClientWithResponsesInterface_UpdateClientWithResponse_Call{Call: _e.mock.On("UpdateClientWithResponse", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_UpdateClientWithResponse_Call) Run(run func(ctx context.Context, id string, body queryservice.ClientUpdate, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateClientWithResponse_Call) Run(run func(ctx context.Context, id string, body queryapi.ClientUpdate, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateClientWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(string), args[2].(queryservice.ClientUpdate), variadicArgs...) + run(args[0].(context.Context), args[1].(string), args[2].(queryapi.ClientUpdate), variadicArgs...) }) return _c } -func (_c *MockClientWithResponsesInterface_UpdateClientWithResponse_Call) Return(_a0 *queryservice.UpdateClientResponse, _a1 error) *MockClientWithResponsesInterface_UpdateClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateClientWithResponse_Call) Return(_a0 *queryapi.UpdateClientResponse, _a1 error) *MockClientWithResponsesInterface_UpdateClientWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_UpdateClientWithResponse_Call) RunAndReturn(run func(context.Context, string, queryservice.ClientUpdate, ...queryservice.RequestEditorFn) (*queryservice.UpdateClientResponse, error)) *MockClientWithResponsesInterface_UpdateClientWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateClientWithResponse_Call) RunAndReturn(run func(context.Context, string, queryapi.ClientUpdate, ...queryapi.RequestEditorFn) (*queryapi.UpdateClientResponse, error)) *MockClientWithResponsesInterface_UpdateClientWithResponse_Call { _c.Call.Return(run) return _c } // UpdateQueryWithBodyWithResponse provides a mock function with given fields: ctx, id, contentType, body, reqEditors -func (_m *MockClientWithResponsesInterface) UpdateQueryWithBodyWithResponse(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn) (*queryservice.UpdateQueryResponse, error) { +func (_m *MockClientWithResponsesInterface) UpdateQueryWithBodyWithResponse(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn) (*queryapi.UpdateQueryResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1460,20 +1534,20 @@ func (_m *MockClientWithResponsesInterface) UpdateQueryWithBodyWithResponse(ctx panic("no return value specified for UpdateQueryWithBodyWithResponse") } - var r0 *queryservice.UpdateQueryResponse + var r0 *queryapi.UpdateQueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.UpdateQueryResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.UpdateQueryResponse, error)); ok { return rf(ctx, id, contentType, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) *queryservice.UpdateQueryResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) *queryapi.UpdateQueryResponse); ok { r0 = rf(ctx, id, contentType, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.UpdateQueryResponse) + r0 = ret.Get(0).(*queryapi.UpdateQueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, contentType, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1492,18 +1566,18 @@ type MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call struc // - id uuid.UUID // - contentType string // - body io.Reader -// - reqEditors ...queryservice.RequestEditorFn +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) UpdateQueryWithBodyWithResponse(ctx interface{}, id interface{}, contentType interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call { return &MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call{Call: _e.mock.On("UpdateQueryWithBodyWithResponse", append([]interface{}{ctx, id, contentType, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, contentType string, body io.Reader, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-4) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-4) for i, a := range args[4:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(string), args[3].(io.Reader), variadicArgs...) @@ -1511,18 +1585,18 @@ func (_c *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call) return _c } -func (_c *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call) Return(_a0 *queryservice.UpdateQueryResponse, _a1 error) *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call) Return(_a0 *queryapi.UpdateQueryResponse, _a1 error) *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryservice.RequestEditorFn) (*queryservice.UpdateQueryResponse, error)) *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, string, io.Reader, ...queryapi.RequestEditorFn) (*queryapi.UpdateQueryResponse, error)) *MockClientWithResponsesInterface_UpdateQueryWithBodyWithResponse_Call { _c.Call.Return(run) return _c } // UpdateQueryWithResponse provides a mock function with given fields: ctx, id, body, reqEditors -func (_m *MockClientWithResponsesInterface) UpdateQueryWithResponse(ctx context.Context, id uuid.UUID, body queryservice.QueryUpdate, reqEditors ...queryservice.RequestEditorFn) (*queryservice.UpdateQueryResponse, error) { +func (_m *MockClientWithResponsesInterface) UpdateQueryWithResponse(ctx context.Context, id uuid.UUID, body queryapi.QueryUpdate, reqEditors ...queryapi.RequestEditorFn) (*queryapi.UpdateQueryResponse, error) { _va := make([]interface{}, len(reqEditors)) for _i := range reqEditors { _va[_i] = reqEditors[_i] @@ -1536,20 +1610,20 @@ func (_m *MockClientWithResponsesInterface) UpdateQueryWithResponse(ctx context. panic("no return value specified for UpdateQueryWithResponse") } - var r0 *queryservice.UpdateQueryResponse + var r0 *queryapi.UpdateQueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) (*queryservice.UpdateQueryResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) (*queryapi.UpdateQueryResponse, error)); ok { return rf(ctx, id, body, reqEditors...) } - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) *queryservice.UpdateQueryResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) *queryapi.UpdateQueryResponse); ok { r0 = rf(ctx, id, body, reqEditors...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*queryservice.UpdateQueryResponse) + r0 = ret.Get(0).(*queryapi.UpdateQueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) error); ok { r1 = rf(ctx, id, body, reqEditors...) } else { r1 = ret.Error(1) @@ -1566,32 +1640,32 @@ type MockClientWithResponsesInterface_UpdateQueryWithResponse_Call struct { // UpdateQueryWithResponse is a helper method to define mock.On call // - ctx context.Context // - id uuid.UUID -// - body queryservice.QueryUpdate -// - reqEditors ...queryservice.RequestEditorFn +// - body queryapi.QueryUpdate +// - reqEditors ...queryapi.RequestEditorFn func (_e *MockClientWithResponsesInterface_Expecter) UpdateQueryWithResponse(ctx interface{}, id interface{}, body interface{}, reqEditors ...interface{}) *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call { return &MockClientWithResponsesInterface_UpdateQueryWithResponse_Call{Call: _e.mock.On("UpdateQueryWithResponse", append([]interface{}{ctx, id, body}, reqEditors...)...)} } -func (_c *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryservice.QueryUpdate, reqEditors ...queryservice.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call) Run(run func(ctx context.Context, id uuid.UUID, body queryapi.QueryUpdate, reqEditors ...queryapi.RequestEditorFn)) *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]queryservice.RequestEditorFn, len(args)-3) + variadicArgs := make([]queryapi.RequestEditorFn, len(args)-3) for i, a := range args[3:] { if a != nil { - variadicArgs[i] = a.(queryservice.RequestEditorFn) + variadicArgs[i] = a.(queryapi.RequestEditorFn) } } - run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryservice.QueryUpdate), variadicArgs...) + run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(queryapi.QueryUpdate), variadicArgs...) }) return _c } -func (_c *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call) Return(_a0 *queryservice.UpdateQueryResponse, _a1 error) *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call) Return(_a0 *queryapi.UpdateQueryResponse, _a1 error) *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryservice.QueryUpdate, ...queryservice.RequestEditorFn) (*queryservice.UpdateQueryResponse, error)) *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call { +func (_c *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call) RunAndReturn(run func(context.Context, uuid.UUID, queryapi.QueryUpdate, ...queryapi.RequestEditorFn) (*queryapi.UpdateQueryResponse, error)) *MockClientWithResponsesInterface_UpdateQueryWithResponse_Call { _c.Call.Return(run) return _c } diff --git a/pkg/queryService/api.gen.go b/pkg/queryAPI/api.gen.go similarity index 77% rename from pkg/queryService/api.gen.go rename to pkg/queryAPI/api.gen.go index d88c069f..bf87e3b1 100644 --- a/pkg/queryService/api.gen.go +++ b/pkg/queryAPI/api.gen.go @@ -1,7 +1,7 @@ -// Package queryservice provides primitives to interact with the openapi HTTP API. +// Package queryapi provides primitives to interact with the openapi HTTP API. // // Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.4.1 DO NOT EDIT. -package queryservice +package queryapi import ( "bytes" @@ -170,19 +170,37 @@ type DocClient struct { // Document The document properties. type Document struct { - // Bucket The bucket containing the document - Bucket string `json:"bucket"` + // ClientId The client external id + ClientId ClientID `json:"client_id"` + + // Fields The fields and the value for the document + Fields map[string]interface{} `json:"fields"` + + // Hash The document hash + Hash Hash `json:"hash"` // Id The document id. Id DocumentID `json:"id"` - - // Key The path to the document - Key string `json:"key"` } // DocumentID The document id. type DocumentID = openapi_types.UUID +// DocumentSummary The document summary properties. +type DocumentSummary struct { + // Hash The document hash + Hash Hash `json:"hash"` + + // Id The document id. + Id DocumentID `json:"id"` +} + +// ErrorMessage Description of error +type ErrorMessage struct { + // Message Message describing the cause. + Message string `json:"message"` +} + // ExportDetails Payload for export trigger response. type ExportDetails struct { // ClientId The client external id @@ -231,6 +249,9 @@ type FieldFilter struct { // FieldFilterCondition The possible field filtering conditions. type FieldFilterCondition string +// Hash The document hash +type Hash = string + // IdMessage A single uuid. type IdMessage struct { // Id Unique identifier for entity. @@ -238,7 +259,7 @@ type IdMessage struct { } // ListDocuments The documents in the client. -type ListDocuments = []Document +type ListDocuments = []DocumentSummary // ListQueries A set of queries. type ListQueries struct { @@ -321,6 +342,18 @@ type RequiredQueryIDs = []QueryID // Version The desired version. type Version = int32 +// InternalError Description of error +type InternalError = ErrorMessage + +// InvalidRequest Description of error +type InvalidRequest = ErrorMessage + +// TooManyRequests Description of error +type TooManyRequests = ErrorMessage + +// Unauthorized Description of error +type Unauthorized = ErrorMessage + // CreateClientJSONRequestBody defines body for CreateClient for application/json ContentType. type CreateClientJSONRequestBody = ClientCreate @@ -447,6 +480,9 @@ type ClientInterface interface { // GetStatusByClientId request GetStatusByClientId(ctx context.Context, id ClientID, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetDocument request + GetDocument(ctx context.Context, id DocumentID, reqEditors ...RequestEditorFn) (*http.Response, error) + // ExportState request ExportState(ctx context.Context, id ExportID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -616,6 +652,18 @@ func (c *Client) GetStatusByClientId(ctx context.Context, id ClientID, reqEditor return c.Client.Do(req) } +func (c *Client) GetDocument(ctx context.Context, id DocumentID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetDocumentRequest(c.Server, id) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) ExportState(ctx context.Context, id ExportID, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewExportStateRequest(c.Server, id) if err != nil { @@ -1041,6 +1089,40 @@ func NewGetStatusByClientIdRequest(server string, id ClientID) (*http.Request, e return req, nil } +// NewGetDocumentRequest generates requests for GetDocument +func NewGetDocumentRequest(server string, id DocumentID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "id", runtime.ParamLocationPath, id) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/document/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewExportStateRequest generates requests for ExportState func NewExportStateRequest(server string, id ExportID) (*http.Request, error) { var err error @@ -1345,6 +1427,9 @@ type ClientWithResponsesInterface interface { // GetStatusByClientIdWithResponse request GetStatusByClientIdWithResponse(ctx context.Context, id ClientID, reqEditors ...RequestEditorFn) (*GetStatusByClientIdResponse, error) + // GetDocumentWithResponse request + GetDocumentWithResponse(ctx context.Context, id DocumentID, reqEditors ...RequestEditorFn) (*GetDocumentResponse, error) + // ExportStateWithResponse request ExportStateWithResponse(ctx context.Context, id ExportID, reqEditors ...RequestEditorFn) (*ExportStateResponse, error) @@ -1374,6 +1459,10 @@ type CreateClientResponse struct { Body []byte HTTPResponse *http.Response JSON201 *ClientIDBody + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1396,6 +1485,10 @@ type GetClientResponse struct { Body []byte HTTPResponse *http.Response JSON200 *DocClient + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1417,6 +1510,10 @@ func (r GetClientResponse) StatusCode() int { type UpdateClientResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1439,6 +1536,10 @@ type GetCollectorByClientIdResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Collector + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1460,6 +1561,10 @@ func (r GetCollectorByClientIdResponse) StatusCode() int { type SetCollectorByClientIdResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1482,6 +1587,10 @@ type ListDocumentsByClientIdResponse struct { Body []byte HTTPResponse *http.Response JSON200 *ListDocuments + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1504,6 +1613,10 @@ type TriggerExportResponse struct { Body []byte HTTPResponse *http.Response JSON201 *IdMessage + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1526,6 +1639,10 @@ type GetStatusByClientIdResponse struct { Body []byte HTTPResponse *http.Response JSON200 *ClientStatusBody + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1544,10 +1661,40 @@ func (r GetStatusByClientIdResponse) StatusCode() int { return 0 } +type GetDocumentResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Document + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError +} + +// Status returns HTTPResponse.Status +func (r GetDocumentResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetDocumentResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type ExportStateResponse struct { Body []byte HTTPResponse *http.Response JSON200 *ExportDetails + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1570,6 +1717,10 @@ type ListQueriesResponse struct { Body []byte HTTPResponse *http.Response JSON200 *ListQueries + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1592,6 +1743,10 @@ type CreateQueryResponse struct { Body []byte HTTPResponse *http.Response JSON201 *IdMessage + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1614,6 +1769,10 @@ type GetQueryResponse struct { Body []byte HTTPResponse *http.Response JSON200 *Query + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1635,6 +1794,10 @@ func (r GetQueryResponse) StatusCode() int { type UpdateQueryResponse struct { Body []byte HTTPResponse *http.Response + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1657,6 +1820,10 @@ type TestQueryResponse struct { Body []byte HTTPResponse *http.Response JSON200 *QueryTestResponse + JSON400 *InvalidRequest + JSON401 *Unauthorized + JSON429 *TooManyRequests + JSON500 *InternalError } // Status returns HTTPResponse.Status @@ -1779,6 +1946,15 @@ func (c *ClientWithResponses) GetStatusByClientIdWithResponse(ctx context.Contex return ParseGetStatusByClientIdResponse(rsp) } +// GetDocumentWithResponse request returning *GetDocumentResponse +func (c *ClientWithResponses) GetDocumentWithResponse(ctx context.Context, id DocumentID, reqEditors ...RequestEditorFn) (*GetDocumentResponse, error) { + rsp, err := c.GetDocument(ctx, id, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetDocumentResponse(rsp) +} + // ExportStateWithResponse request returning *ExportStateResponse func (c *ClientWithResponses) ExportStateWithResponse(ctx context.Context, id ExportID, reqEditors ...RequestEditorFn) (*ExportStateResponse, error) { rsp, err := c.ExportState(ctx, id, reqEditors...) @@ -1878,6 +2054,34 @@ func ParseCreateClientResponse(rsp *http.Response) (*CreateClientResponse, error } response.JSON201 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -1904,6 +2108,34 @@ func ParseGetClientResponse(rsp *http.Response) (*GetClientResponse, error) { } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -1922,6 +2154,37 @@ func ParseUpdateClientResponse(rsp *http.Response) (*UpdateClientResponse, error HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + return response, nil } @@ -1946,6 +2209,34 @@ func ParseGetCollectorByClientIdResponse(rsp *http.Response) (*GetCollectorByCli } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -1964,6 +2255,37 @@ func ParseSetCollectorByClientIdResponse(rsp *http.Response) (*SetCollectorByCli HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + return response, nil } @@ -1988,6 +2310,34 @@ func ParseListDocumentsByClientIdResponse(rsp *http.Response) (*ListDocumentsByC } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -2014,6 +2364,34 @@ func ParseTriggerExportResponse(rsp *http.Response) (*TriggerExportResponse, err } response.JSON201 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -2040,6 +2418,88 @@ func ParseGetStatusByClientIdResponse(rsp *http.Response) (*GetStatusByClientIdR } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + +// ParseGetDocumentResponse parses an HTTP response from a GetDocumentWithResponse call +func ParseGetDocumentResponse(rsp *http.Response) (*GetDocumentResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetDocumentResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Document + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -2066,6 +2526,34 @@ func ParseExportStateResponse(rsp *http.Response) (*ExportStateResponse, error) } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -2092,6 +2580,34 @@ func ParseListQueriesResponse(rsp *http.Response) (*ListQueriesResponse, error) } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -2118,6 +2634,34 @@ func ParseCreateQueryResponse(rsp *http.Response) (*CreateQueryResponse, error) } response.JSON201 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -2144,6 +2688,34 @@ func ParseGetQueryResponse(rsp *http.Response) (*GetQueryResponse, error) { } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil @@ -2162,6 +2734,37 @@ func ParseUpdateQueryResponse(rsp *http.Response) (*UpdateQueryResponse, error) HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + return response, nil } @@ -2186,6 +2789,34 @@ func ParseTestQueryResponse(rsp *http.Response) (*TestQueryResponse, error) { } response.JSON200 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest InvalidRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Unauthorized + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + } return response, nil diff --git a/scripts/database.yml b/scripts/database.yml index a2f4a1b8..8dc2ff46 100644 --- a/scripts/database.yml +++ b/scripts/database.yml @@ -21,6 +21,13 @@ tasks: cmds: - task compose:up:generate - sqlc vet --file sqlc.yml + - | + exit 0 + for file in database/migrations/*.sql; do + if [[ -f "$file" ]]; then + sqlcheck -c -f $file -r 3 # move to 1 + fi + done mig:create: cmds: - | diff --git a/scripts/openapi-scripts.yml b/scripts/openapi-scripts.yml index b93a9ab4..c40193c4 100644 --- a/scripts/openapi-scripts.yml +++ b/scripts/openapi-scripts.yml @@ -7,8 +7,12 @@ tasks: lint: cmds: - | - vacuum lint ./serviceAPIs/queryService.yaml -b -d -e --no-clip -z \ - {{.CLI_ARGS}} + for file in serviceAPIs/*.yml serviceAPIs/*.yaml; do + if [[ -f "$file" ]]; then + vacuum lint $file -b -d --no-clip -z -n info -s \ + -r vaccum.conf.yaml {{.CLI_ARGS}} + fi + done generate: - | generateGo() { diff --git a/serviceAPIs/queryService.yaml b/serviceAPIs/queryAPI.yaml similarity index 80% rename from serviceAPIs/queryService.yaml rename to serviceAPIs/queryAPI.yaml index a6293a20..9b052b00 100644 --- a/serviceAPIs/queryService.yaml +++ b/serviceAPIs/queryAPI.yaml @@ -4,6 +4,13 @@ info: title: Query Orchestration API description: API documentation for the Query Orchestration services. version: 0.0.1 + contact: + email: mmcguinness@aarete.com + name: Michael McGuinness + url: doczy.com + license: + name: unlicensed + url: "www.example.com" servers: - url: https://doczy.com/v1 description: Production server @@ -14,7 +21,7 @@ tags: description: Operations related to collectors - name: DocumentsService description: Operations related to documents - - name: QueryService + - name: QueryAPI description: Operations related to queries - name: ExportService description: Operations related to exports @@ -48,6 +55,10 @@ paths: $ref: "#/components/schemas/ClientIDBody" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -74,6 +85,10 @@ paths: $ref: "#/components/schemas/DocClient" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" patch: @@ -99,6 +114,10 @@ paths: $ref: "#/components/headers/RateLimit" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -106,7 +125,7 @@ paths: get: operationId: listQueries tags: - - QueryService + - QueryAPI summary: List queries description: Retrieves a list of queries based on filter criteria. security: @@ -123,12 +142,16 @@ paths: $ref: "#/components/schemas/ListQueries" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" post: operationId: createQuery tags: - - QueryService + - QueryAPI summary: Create a new query description: Creates a new query with the provided details. security: @@ -152,6 +175,10 @@ paths: $ref: "#/components/schemas/IdMessage" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -161,7 +188,7 @@ paths: get: operationId: getQuery tags: - - QueryService + - QueryAPI summary: Get a query by ID description: Retrieves a specific query by its ID. security: @@ -178,12 +205,16 @@ paths: $ref: "#/components/schemas/Query" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" patch: operationId: updateQuery tags: - - QueryService + - QueryAPI summary: Update a query description: Updates an existing query with new details. security: @@ -203,6 +234,10 @@ paths: $ref: "#/components/headers/RateLimit" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -212,7 +247,7 @@ paths: post: operationId: testQuery tags: - - QueryService + - QueryAPI summary: Test a query description: Executes a test run of a query with the provided parameters. security: @@ -236,6 +271,10 @@ paths: $ref: "#/components/schemas/QueryTestResponse" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -262,6 +301,10 @@ paths: $ref: "#/components/schemas/ClientStatusBody" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -288,6 +331,10 @@ paths: $ref: "#/components/schemas/Collector" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" patch: @@ -313,6 +360,10 @@ paths: $ref: "#/components/headers/RateLimit" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -339,6 +390,40 @@ paths: $ref: "#/components/schemas/ListDocuments" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" + "500": + $ref: "#/components/responses/InternalError" + + /document/{id}: + parameters: + - $ref: "#/components/parameters/DocumentID" + get: + operationId: getDocument + tags: + - DocumentsService + summary: Get document details by its id + description: Retrieves the details of a document by its id. + security: + - placeholderAuth: [] + responses: + "200": + description: Document details. + headers: + RateLimit: + $ref: "#/components/headers/RateLimit" + content: + application/json: + schema: + $ref: "#/components/schemas/Document" + "400": + $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -372,6 +457,10 @@ paths: $ref: "#/components/schemas/IdMessage" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -398,6 +487,10 @@ paths: $ref: "#/components/schemas/ExportDetails" "400": $ref: "#/components/responses/InvalidRequest" + "401": + $ref: "#/components/responses/Unauthorized" + "429": + $ref: "#/components/responses/TooManyRequests" "500": $ref: "#/components/responses/InternalError" @@ -427,14 +520,23 @@ components: $ref: "#/components/schemas/QueryID" description: The ID of the query. + DocumentID: + in: path + name: id + required: true + schema: + $ref: "#/components/schemas/DocumentID" + description: The document ID. + headers: RateLimit: schema: type: string pattern: "^[0-9]+;window=[0-9]+$" maxLength: 32 + example: 100;window=60 description: Rate limit information in format "limit;window=time-window" - example: "100;window=60" + example: "100;window=10" securitySchemes: placeholderAuth: @@ -449,12 +551,48 @@ components: headers: RateLimit: $ref: "#/components/headers/RateLimit" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" InternalError: description: Internal server error. headers: RateLimit: $ref: "#/components/headers/RateLimit" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" + + TooManyRequests: + description: Response upon too many requests. + headers: + RateLimit: + $ref: "#/components/headers/RateLimit" + Retry-After: + schema: + type: integer + format: int32 + minimum: 0 + maximum: 86400 + description: Number of seconds before trying again. + example: 120 + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" + + Unauthorized: + description: Response when unauthorized. + headers: + RateLimit: + $ref: "#/components/headers/RateLimit" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" schemas: ClientID: @@ -514,7 +652,7 @@ components: type: string description: Configuration for the query. maxLength: 2048 - pattern: '^\{.+\}$' + pattern: '^\{.*\}$' Query: description: A logic unit of execution. @@ -655,7 +793,25 @@ components: description: The documents in the client. maxItems: 256 items: - $ref: "#/components/schemas/Document" + $ref: "#/components/schemas/DocumentSummary" + + Hash: + type: string + description: The document hash + maxLength: 2048 + pattern: "^.+$" + + DocumentSummary: + description: The document summary properties. + type: object + properties: + id: + $ref: "#/components/schemas/DocumentID" + hash: + $ref: "#/components/schemas/Hash" + required: + - id + - hash Document: description: The document properties. @@ -663,20 +819,23 @@ components: properties: id: $ref: "#/components/schemas/DocumentID" - bucket: - type: string - description: The bucket containing the document - maxLength: 256 - pattern: "^.+$" - key: - type: string - description: The path to the document - maxLength: 2048 - pattern: "^.+/.+$" + client_id: + $ref: "#/components/schemas/ClientID" + hash: + $ref: "#/components/schemas/Hash" + fields: + type: object + description: "The fields and the value for the document" + example: + property1: "string value" + property2: 42 + property3: true + property5: [1, 2, 3] required: - id - - bucket - - key + - client_id + - hash + - fields ClientCreate: description: The properties for creation. @@ -771,7 +930,7 @@ components: CollectorFieldName: type: string - pattern: "^[a-zA-Z]+$" + pattern: "^.+$" maxLength: 256 description: The output field name. @@ -871,3 +1030,18 @@ components: required: - client_id - status + + ErrorMessage: + description: Description of error + type: object + properties: + message: + type: string + pattern: "^.+$" + description: Message describing the cause. + maxLength: 256 + example: "you must give me good information" + required: + - message + example: + message: you must include a message diff --git a/test/process_test.go b/test/process_test.go index c91b3b82..8c55b4d3 100644 --- a/test/process_test.go +++ b/test/process_test.go @@ -2,16 +2,15 @@ package endtoend_test import ( "context" - "fmt" + "net/http" "strings" "testing" - "time" "queryorchestration/internal/serviceconfig" "queryorchestration/internal/serviceconfig/objectstore" "queryorchestration/internal/test" - queryservicetest "queryorchestration/internal/test/queryService" - queryservice "queryorchestration/pkg/queryService" + queryapitest "queryorchestration/internal/test/queryAPI" + queryapi "queryorchestration/pkg/queryAPI" "github.com/oapi-codegen/runtime/types" "github.com/stretchr/testify/assert" @@ -32,23 +31,25 @@ func TestProcess(t *testing.T) { net, clean := test.CreateFullNetwork(t, ctx, cfg) defer clean() - client := queryservicetest.CreateClientWithSync(t, ctx, net.Client) + client := queryapitest.CreateClientWithSync(t, ctx, net.Client) - contextQueryRes, err := net.Client.CreateQueryWithResponse(ctx, queryservice.QueryCreate{ - Type: queryservice.CONTEXTFULL, + contextQueryRes, err := net.Client.CreateQueryWithResponse(ctx, queryapi.QueryCreate{ + Type: queryapi.CONTEXTFULL, }) require.NoError(t, err) + require.Equal(t, http.StatusCreated, contextQueryRes.StatusCode()) jcfg := `{"path":"keyone"}` - jsonQueryRes, err := net.Client.CreateQueryWithResponse(ctx, queryservice.QueryCreate{ - Type: queryservice.JSONEXTRACTOR, + jsonQueryRes, err := net.Client.CreateQueryWithResponse(ctx, queryapi.QueryCreate{ + Type: queryapi.JSONEXTRACTOR, Config: &jcfg, RequiredQueries: &[]types.UUID{contextQueryRes.JSON201.Id}, }) require.NoError(t, err) + require.Equal(t, http.StatusCreated, jsonQueryRes.StatusCode()) newActiveVersion := int32(1) - _, err = net.Client.SetCollectorByClientIdWithResponse(ctx, client.Id, queryservice.CollectorSet{ + collRes, err := net.Client.SetCollectorByClientIdWithResponse(ctx, client.Id, queryapi.CollectorSet{ ActiveVersion: &newActiveVersion, - Fields: &[]queryservice.CollectorField{ + Fields: &[]queryapi.CollectorField{ { Name: "JSON_QUERY", QueryId: jsonQueryRes.JSON201.Id, @@ -56,72 +57,75 @@ func TestProcess(t *testing.T) { }, }) require.NoError(t, err) + require.Equal(t, http.StatusOK, collRes.StatusCode()) - WaitForClientStatus(t, ctx, net.Client, client.Id, queryservice.INSYNC) + queryapitest.WaitForClientStatus(t, ctx, net.Client, client.Id, queryapi.INSYNC) body := strings.NewReader(pdfHelloWorld) - location := test.PutObject(t, ctx, cfg, client.Uid, net.Dependencies.BucketName, "object_name", body) + test.PutObject(t, ctx, cfg, client.Uid, net.Dependencies.BucketName, "objectname", body) - WaitForClientStatus(t, ctx, net.Client, client.Id, queryservice.NOTSYNCED) - WaitForClientStatus(t, ctx, net.Client, client.Id, queryservice.INSYNC) + queryapitest.WaitForClientStatus(t, ctx, net.Client, client.Id, queryapi.NOTSYNCED) + queryapitest.WaitForClientStatus(t, ctx, net.Client, client.Id, queryapi.INSYNC) docs, err := net.Client.ListDocumentsByClientIdWithResponse(ctx, client.Id) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, *docs.JSON200, 1) doc := (*docs.JSON200)[0] - assert.Equal(t, net.Dependencies.BucketName, doc.Bucket) - assert.Equal(t, location, doc.Key) - testRes, err := net.Client.TestQueryWithResponse(ctx, jsonQueryRes.JSON201.Id, queryservice.QueryTestRequest{ + expectedDoc := queryapi.Document{ + Id: doc.Id, + Hash: doc.Hash, + ClientId: client.Id, + Fields: map[string]interface{}{ + "JSON_QUERY": "valueone", + }, + } + + docRes, err := net.Client.GetDocumentWithResponse(ctx, doc.Id) + require.NoError(t, err) + require.NotNil(t, docRes) + require.NotNil(t, docRes.JSON200) + fullDoc := *docRes.JSON200 + assert.EqualExportedValues(t, expectedDoc, fullDoc) + + jcfg = `{"path":"keytwo"}` + av := int32(2) + _, err = net.Client.UpdateQueryWithResponse(ctx, jsonQueryRes.JSON201.Id, queryapi.QueryUpdate{ + ActiveVersion: &av, + Config: &jcfg, + }) + require.NoError(t, err) + expectedDoc.Fields = map[string]interface{}{ + "JSON_QUERY": "valuetwo", + } + + queryapitest.WaitForClientStatus(t, ctx, net.Client, client.Id, queryapi.NOTSYNCED) + queryapitest.WaitForClientStatus(t, ctx, net.Client, client.Id, queryapi.INSYNC) + + docRes, err = net.Client.GetDocumentWithResponse(ctx, doc.Id) + require.NoError(t, err) + require.NotNil(t, docRes) + require.NotNil(t, docRes.JSON200) + assert.EqualExportedValues(t, expectedDoc, *docRes.JSON200) + + testRes, err := net.Client.TestQueryWithResponse(ctx, jsonQueryRes.JSON201.Id, queryapi.QueryTestRequest{ QueryVersion: 1, DocumentId: doc.Id, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "valueone", testRes.JSON200.Value) - - aV := int32(2) - jcfg = `{"path":"keytwo"}` - res, err := net.Client.UpdateQueryWithResponse(ctx, jsonQueryRes.JSON201.Id, queryservice.QueryUpdate{ - ActiveVersion: &aV, - Config: &jcfg, - }) - assert.NoError(t, err) - assert.NotNil(t, res) - - WaitForClientStatus(t, ctx, net.Client, client.Id, queryservice.NOTSYNCED) - WaitForClientStatus(t, ctx, net.Client, client.Id, queryservice.INSYNC) - - testRes, err = net.Client.TestQueryWithResponse(ctx, jsonQueryRes.JSON201.Id, queryservice.QueryTestRequest{ + testRes, err = net.Client.TestQueryWithResponse(ctx, jsonQueryRes.JSON201.Id, queryapi.QueryTestRequest{ QueryVersion: 2, DocumentId: doc.Id, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "valuetwo", testRes.JSON200.Value) -} -func WaitForClientStatus(t testing.TB, ctx context.Context, service *queryservice.ClientWithResponses, id string, status queryservice.ClientStatus) { - t.Helper() - - timeout := time.After(30 * time.Second) - ticker := time.NewTicker(500 * time.Millisecond) - defer ticker.Stop() - - for { - select { - case <-timeout: - require.NoError(t, fmt.Errorf("Timeout waiting for client status to become %s", status)) - case <-ticker.C: - jRes, err := service.GetStatusByClientIdWithResponse(ctx, id) - if err != nil { - assert.NoError(t, err) - } - - if jRes.JSON200.Status == status { - assert.Equal(t, status, jRes.JSON200.Status) - return - } - } - } + docRes, err = net.Client.GetDocumentWithResponse(ctx, doc.Id) + require.NoError(t, err) + require.NotNil(t, docRes) + require.NotNil(t, docRes.JSON200) + assert.EqualExportedValues(t, expectedDoc, *docRes.JSON200) } const pdfHelloWorld = `%PDF-1.4 diff --git a/test/queryService/accessory_test.go b/test/queryAPI/accessory_test.go similarity index 67% rename from test/queryService/accessory_test.go rename to test/queryAPI/accessory_test.go index f971a243..9312546e 100644 --- a/test/queryService/accessory_test.go +++ b/test/queryAPI/accessory_test.go @@ -6,40 +6,38 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/require" + "queryorchestration/internal/test" "github.com/stretchr/testify/assert" ) -func TestQueryServiceAccessories(t *testing.T) { +func TestQueryAPIAccessories(t *testing.T) { ctx := context.Background() - c, cleanup := test.CreateServiceNetwork(t, ctx, &test.ServiceNetworkConfig{ - Name: test.QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": "iamthere", - }, + c, cleanup := test.CreateAPINetwork(t, ctx, &test.ServiceNetworkConfig{ + API: test.QueryAPI, }) defer cleanup() resp, err := http.Get(fmt.Sprintf("%s/swagger/doc.json", c.URI)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, http.StatusOK, resp.StatusCode) resp, err = http.Get(fmt.Sprintf("%s/swagger/doc.yaml", c.URI)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, http.StatusOK, resp.StatusCode) resp, err = http.Get(fmt.Sprintf("%s/swagger/index.html", c.URI)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, http.StatusOK, resp.StatusCode) resp, err = http.Get(fmt.Sprintf("%s/metrics", c.URI)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, http.StatusOK, resp.StatusCode) } diff --git a/test/queryService/client_test.go b/test/queryAPI/client_test.go similarity index 51% rename from test/queryService/client_test.go rename to test/queryAPI/client_test.go index e6d37f81..2ada2612 100644 --- a/test/queryService/client_test.go +++ b/test/queryAPI/client_test.go @@ -2,56 +2,60 @@ package endtoend import ( "context" + "net/http" "testing" "queryorchestration/internal/test" - queryservice "queryorchestration/pkg/queryService" + queryapi "queryorchestration/pkg/queryAPI" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestClient(t *testing.T) { ctx := context.Background() - c, cleanup := test.CreateServiceNetwork(t, ctx, &test.ServiceNetworkConfig{ - Name: test.QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": "iamthere", - }, + c, cleanup := test.CreateAPINetwork(t, ctx, &test.ServiceNetworkConfig{ + API: test.QueryAPI, }) defer cleanup() - client, err := queryservice.NewClientWithResponses(c.URI) - assert.NoError(t, err) + client, err := queryapi.NewClientWithResponses(c.URI) + require.NoError(t, err) - idRes, err := client.CreateClientWithResponse(ctx, queryservice.ClientCreate{ + clientErrRes, err := client.GetClientWithResponse(ctx, "INVALID") + require.NoError(t, err) + assert.Equal(t, http.StatusBadRequest, clientErrRes.StatusCode()) + assert.Equal(t, "Unable to get client: no rows in result set", clientErrRes.JSON400.Message) + + idRes, err := client.CreateClientWithResponse(ctx, queryapi.ClientCreate{ Name: "example_name", Id: "EXA", }) - assert.NoError(t, err) - assert.NotNil(t, idRes) + require.NoError(t, err) + require.Equal(t, http.StatusCreated, idRes.StatusCode()) assert.NotNil(t, idRes.JSON201) - assert.NotNil(t, idRes.JSON201.Id) + assert.Equal(t, "EXA", idRes.JSON201.Id) id := idRes.JSON201.Id clientRes, err := client.GetClientWithResponse(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) + require.Equal(t, http.StatusOK, clientRes.StatusCode()) assert.Equal(t, id, clientRes.JSON200.Id) assert.Equal(t, "example_name", clientRes.JSON200.Name) assert.False(t, clientRes.JSON200.CanSync) updateName := "update_name" updateCanSync := true - updateRes, err := client.UpdateClientWithResponse(ctx, id, queryservice.ClientUpdate{ + updateRes, err := client.UpdateClientWithResponse(ctx, id, queryapi.ClientUpdate{ Name: &updateName, CanSync: &updateCanSync, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, updateRes) clientRes, err = client.GetClientWithResponse(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, clientRes.JSON200.Id) assert.Equal(t, updateName, clientRes.JSON200.Name) assert.True(t, clientRes.JSON200.CanSync) diff --git a/test/queryService/collectorservice_test.go b/test/queryAPI/collectorservice_test.go similarity index 72% rename from test/queryService/collectorservice_test.go rename to test/queryAPI/collectorservice_test.go index 1e7420bf..9dc74548 100644 --- a/test/queryService/collectorservice_test.go +++ b/test/queryAPI/collectorservice_test.go @@ -8,7 +8,9 @@ import ( "queryorchestration/internal/serviceconfig" "queryorchestration/internal/serviceconfig/queue" "queryorchestration/internal/test" - queryservice "queryorchestration/pkg/queryService" + queryapi "queryorchestration/pkg/queryAPI" + + "github.com/stretchr/testify/require" "github.com/oapi-codegen/runtime/types" "github.com/stretchr/testify/assert" @@ -35,46 +37,42 @@ func TestCollectorService(t *testing.T) { defer clean() test.SetQueueClient(t, ctx, cfg) - clientsyncurl := test.CreateQueue(t, ctx, cfg, test.ClientSyncRunner) + clientsyncurl := test.CreateQueue(t, ctx, cfg, test.ClientSyncRunnerName) - c, cleanup := test.CreateServiceNetwork(t, ctx, &test.ServiceNetworkConfig{ + c, cleanup := test.CreateAPINetwork(t, ctx, &test.ServiceNetworkConfig{ Cfg: cfg, Network: network, - Name: test.QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": clientsyncurl, - "QUERY_VERSION_SYNC_URL": "iamthere", - }, + API: test.QueryAPI, }) defer cleanup() - client, err := queryservice.NewClientWithResponses(c.URI) - assert.NoError(t, err) + client, err := queryapi.NewClientWithResponses(c.URI) + require.NoError(t, err) - contextRes, err := client.CreateQueryWithResponse(ctx, queryservice.QueryCreate{ - Type: queryservice.CONTEXTFULL, + contextRes, err := client.CreateQueryWithResponse(ctx, queryapi.QueryCreate{ + Type: queryapi.CONTEXTFULL, }) - assert.NoError(t, err) + require.NoError(t, err) jsoncfg := "{\"path\":\"key\"}" - jsonRes, err := client.CreateQueryWithResponse(ctx, queryservice.QueryCreate{ - Type: queryservice.JSONEXTRACTOR, + jsonRes, err := client.CreateQueryWithResponse(ctx, queryapi.QueryCreate{ + Type: queryapi.JSONEXTRACTOR, Config: &jsoncfg, RequiredQueries: &[]types.UUID{ contextRes.JSON201.Id, }, }) - assert.NoError(t, err) + require.NoError(t, err) - clientRes, err := client.CreateClientWithResponse(ctx, queryservice.ClientCreate{ + clientRes, err := client.CreateClientWithResponse(ctx, queryapi.ClientCreate{ Name: "example_name", Id: "ID", }) - assert.NoError(t, err) + require.NoError(t, err) id := clientRes.JSON201.Id collRes, err := client.GetCollectorByClientIdWithResponse(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, collRes.JSON200.ClientId) assert.Equal(t, int32(0), collRes.JSON200.ActiveVersion) assert.Equal(t, int32(0), collRes.JSON200.LatestVersion) @@ -83,24 +81,24 @@ func TestCollectorService(t *testing.T) { assert.Len(t, collRes.JSON200.Fields, 0) av := int32(1) - fields := []queryservice.CollectorField{ + fields := []queryapi.CollectorField{ { Name: "json", QueryId: jsonRes.JSON201.Id, }, } minVersion := int64(1000) - uRes, err := client.SetCollectorByClientIdWithResponse(ctx, id, queryservice.CollectorSet{ + uRes, err := client.SetCollectorByClientIdWithResponse(ctx, id, queryapi.CollectorSet{ ActiveVersion: &av, MinimumCleanerVersion: &minVersion, MinimumTextVersion: &minVersion, Fields: &fields, }) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, 200, uRes.StatusCode()) collRes, err = client.GetCollectorByClientIdWithResponse(ctx, id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, id, collRes.JSON200.ClientId) assert.Equal(t, int32(1), collRes.JSON200.ActiveVersion) assert.Equal(t, int32(1), collRes.JSON200.LatestVersion) diff --git a/test/queryAPI/exportservice_test.go b/test/queryAPI/exportservice_test.go new file mode 100644 index 00000000..f3746f09 --- /dev/null +++ b/test/queryAPI/exportservice_test.go @@ -0,0 +1,29 @@ +package endtoend + +import ( + "context" + "testing" + + "queryorchestration/internal/test" + queryapi "queryorchestration/pkg/queryAPI" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" +) + +func TestExportService(t *testing.T) { + ctx := context.Background() + + c, cleanup := test.CreateAPINetwork(t, ctx, &test.ServiceNetworkConfig{ + API: test.QueryAPI, + }) + defer cleanup() + + client, err := queryapi.NewClientWithResponses(c.URI) + require.NoError(t, err) + + idRes, err := client.TriggerExportWithResponse(ctx, "CLIENT_ID", queryapi.ExportTrigger{}) + require.NoError(t, err) + assert.NotNil(t, idRes) +} diff --git a/test/queryService/queryservice_test.go b/test/queryAPI/queryservice_test.go similarity index 66% rename from test/queryService/queryservice_test.go rename to test/queryAPI/queryservice_test.go index 7863c73d..c5c89cfd 100644 --- a/test/queryService/queryservice_test.go +++ b/test/queryAPI/queryservice_test.go @@ -10,7 +10,9 @@ import ( "queryorchestration/internal/serviceconfig" "queryorchestration/internal/serviceconfig/queue" "queryorchestration/internal/test" - queryservice "queryorchestration/pkg/queryService" + queryapi "queryorchestration/pkg/queryAPI" + + "github.com/stretchr/testify/require" "github.com/oapi-codegen/runtime/types" "github.com/stretchr/testify/assert" @@ -21,7 +23,7 @@ type QueryConfig struct { queue.QueueConfig } -func TestQueryService(t *testing.T) { +func TestQueryAPI(t *testing.T) { ctx := context.Background() cfg := &QueryConfig{} @@ -38,69 +40,67 @@ func TestQueryService(t *testing.T) { defer clean() err := cfg.SetQueueClient(ctx) - assert.NoError(t, err) - queryversionsyncurl := test.CreateQueue(t, ctx, cfg, test.QueryVersionSyncRunner) + require.NoError(t, err) + queryversionsyncurl := test.CreateQueue(t, ctx, cfg, test.QueryVersionSyncRunnerName) - c, cleanup := test.CreateServiceNetwork(t, ctx, &test.ServiceNetworkConfig{ + c, cleanup := test.CreateAPINetwork(t, ctx, &test.ServiceNetworkConfig{ Cfg: cfg, Network: network, - Name: test.QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": queryversionsyncurl, - }, + API: test.QueryAPI, }) defer cleanup() - client, err := queryservice.NewClientWithResponses(c.URI) - assert.NoError(t, err) + client, err := queryapi.NewClientWithResponses(c.URI) + require.NoError(t, err) - idRes, err := client.CreateQueryWithResponse(ctx, queryservice.QueryCreate{ - Type: queryservice.CONTEXTFULL, + idRes, err := client.CreateQueryWithResponse(ctx, queryapi.QueryCreate{ + Type: queryapi.CONTEXTFULL, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, idRes) assert.NotNil(t, idRes.JSON201) contextID := idRes.JSON201.Id assert.NotEmpty(t, contextID) jcfg := "{}" - idRes, err = client.CreateQueryWithResponse(ctx, queryservice.QueryCreate{ - Type: queryservice.JSONEXTRACTOR, + idRes, err = client.CreateQueryWithResponse(ctx, queryapi.QueryCreate{ + Type: queryapi.JSONEXTRACTOR, Config: &jcfg, }) - assert.NoError(t, err) + require.NoError(t, err) + assert.NotNil(t, idRes) + assert.NotNil(t, idRes.JSON201) jsonID := idRes.JSON201.Id queryRes, err := client.GetQueryWithResponse(ctx, jsonID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, jsonID, queryRes.JSON200.Id) - assert.Equal(t, queryservice.JSONEXTRACTOR, queryRes.JSON200.Type) + assert.Equal(t, queryapi.JSONEXTRACTOR, queryRes.JSON200.Type) assert.Equal(t, int32(1), queryRes.JSON200.ActiveVersion) assert.Equal(t, int32(1), queryRes.JSON200.LatestVersion) assert.Equal(t, jcfg, *queryRes.JSON200.Config) assert.Nil(t, queryRes.JSON200.RequiredQueries) queriesRes, err := client.ListQueriesWithResponse(ctx) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, queriesRes.JSON200.Queries, 2) aV := int32(2) - res, err := client.UpdateQueryWithResponse(ctx, jsonID, queryservice.QueryUpdate{ + res, err := client.UpdateQueryWithResponse(ctx, jsonID, queryapi.QueryUpdate{ ActiveVersion: &aV, RequiredQueries: &[]types.UUID{ contextID, }, }) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, res) test.AssertMessageBody(t, ctx, cfg, queryversionsyncurl, regexp.MustCompile(`{"id":".+"}`)) queryRes, err = client.GetQueryWithResponse(ctx, jsonID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, jsonID, queryRes.JSON200.Id) - assert.Equal(t, queryservice.JSONEXTRACTOR, queryRes.JSON200.Type) + assert.Equal(t, queryapi.JSONEXTRACTOR, queryRes.JSON200.Type) assert.Equal(t, int32(2), queryRes.JSON200.ActiveVersion) assert.Equal(t, int32(2), queryRes.JSON200.LatestVersion) assert.Equal(t, jcfg, *queryRes.JSON200.Config) diff --git a/test/queryService/exportservice_test.go b/test/queryService/exportservice_test.go deleted file mode 100644 index a425cb57..00000000 --- a/test/queryService/exportservice_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package endtoend - -import ( - "context" - "testing" - - "queryorchestration/internal/test" - queryservice "queryorchestration/pkg/queryService" - - "github.com/stretchr/testify/assert" -) - -func TestExportService(t *testing.T) { - ctx := context.Background() - - c, cleanup := test.CreateServiceNetwork(t, ctx, &test.ServiceNetworkConfig{ - Name: test.QueryService, - Env: map[string]string{ - "CLIENT_SYNC_URL": "/i/am/here", - "QUERY_VERSION_SYNC_URL": "iamthere", - }, - }) - defer cleanup() - - client, err := queryservice.NewClientWithResponses(c.URI) - assert.NoError(t, err) - - idRes, err := client.TriggerExportWithResponse(ctx, "CLIENT_ID", queryservice.ExportTrigger{}) - assert.NoError(t, err) - assert.NotNil(t, idRes) -} diff --git a/vaccum.conf.yaml b/vaccum.conf.yaml index e69de29b..14b16791 100644 --- a/vaccum.conf.yaml +++ b/vaccum.conf.yaml @@ -0,0 +1,5 @@ +--- +extends: [[spectral:oas, recommended], [vacuum:owasp, all]] +rules: + post-response-success: false + oas3-missing-example: false diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/authentication_input.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/authentication_input.go new file mode 100644 index 00000000..a53484b9 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/authentication_input.go @@ -0,0 +1,29 @@ +package openapi3filter + +import ( + "fmt" + + "github.com/getkin/kin-openapi/openapi3" +) + +type AuthenticationInput struct { + RequestValidationInput *RequestValidationInput + SecuritySchemeName string + SecurityScheme *openapi3.SecurityScheme + Scopes []string +} + +func (input *AuthenticationInput) NewError(err error) error { + if err == nil { + if len(input.Scopes) == 0 { + err = fmt.Errorf("security requirement %q failed", input.SecuritySchemeName) + } else { + err = fmt.Errorf("security requirement %q (scopes: %+v) failed", input.SecuritySchemeName, input.Scopes) + } + } + return &RequestError{ + Input: input.RequestValidationInput, + Reason: "authorization failed", + Err: err, + } +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/errors.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/errors.go new file mode 100644 index 00000000..ea7c7c31 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/errors.go @@ -0,0 +1,97 @@ +package openapi3filter + +import ( + "bytes" + "fmt" + + "github.com/getkin/kin-openapi/openapi3" +) + +var _ error = &RequestError{} + +// RequestError is returned by ValidateRequest when request does not match OpenAPI spec +type RequestError struct { + Input *RequestValidationInput + Parameter *openapi3.Parameter + RequestBody *openapi3.RequestBody + Reason string + Err error +} + +var _ interface{ Unwrap() error } = RequestError{} + +func (err *RequestError) Error() string { + reason := err.Reason + if e := err.Err; e != nil { + if len(reason) == 0 || reason == e.Error() { + reason = e.Error() + } else { + reason += ": " + e.Error() + } + } + if v := err.Parameter; v != nil { + return fmt.Sprintf("parameter %q in %s has an error: %s", v.Name, v.In, reason) + } else if v := err.RequestBody; v != nil { + return fmt.Sprintf("request body has an error: %s", reason) + } else { + return reason + } +} + +func (err RequestError) Unwrap() error { + return err.Err +} + +var _ error = &ResponseError{} + +// ResponseError is returned by ValidateResponse when response does not match OpenAPI spec +type ResponseError struct { + Input *ResponseValidationInput + Reason string + Err error +} + +var _ interface{ Unwrap() error } = ResponseError{} + +func (err *ResponseError) Error() string { + reason := err.Reason + if e := err.Err; e != nil { + if len(reason) == 0 { + reason = e.Error() + } else { + reason += ": " + e.Error() + } + } + return reason +} + +func (err ResponseError) Unwrap() error { + return err.Err +} + +var _ error = &SecurityRequirementsError{} + +// SecurityRequirementsError is returned by ValidateSecurityRequirements +// when no requirement is met. +type SecurityRequirementsError struct { + SecurityRequirements openapi3.SecurityRequirements + Errors []error +} + +func (err *SecurityRequirementsError) Error() string { + buff := bytes.NewBufferString("security requirements failed: ") + for i, e := range err.Errors { + buff.WriteString(e.Error()) + if i != len(err.Errors)-1 { + buff.WriteString(" | ") + } + } + + return buff.String() +} + +var _ interface{ Unwrap() []error } = SecurityRequirementsError{} + +func (err SecurityRequirementsError) Unwrap() []error { + return err.Errors +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/internal.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/internal.go new file mode 100644 index 00000000..f807e06f --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/internal.go @@ -0,0 +1,25 @@ +package openapi3filter + +import ( + "reflect" + "strings" +) + +func parseMediaType(contentType string) string { + i := strings.IndexByte(contentType, ';') + if i < 0 { + return contentType + } + return contentType[:i] +} + +func isNilValue(value any) bool { + if value == nil { + return true + } + switch reflect.TypeOf(value).Kind() { + case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice: + return reflect.ValueOf(value).IsNil() + } + return false +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/middleware.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/middleware.go new file mode 100644 index 00000000..d20889ed --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/middleware.go @@ -0,0 +1,284 @@ +package openapi3filter + +import ( + "bytes" + "context" + "io" + "log" + "net/http" + + "github.com/getkin/kin-openapi/routers" +) + +// Validator provides HTTP request and response validation middleware. +type Validator struct { + router routers.Router + errFunc ErrFunc + logFunc LogFunc + strict bool + options Options +} + +// ErrFunc handles errors that may occur during validation. +type ErrFunc func(ctx context.Context, w http.ResponseWriter, status int, code ErrCode, err error) + +// LogFunc handles log messages that may occur during validation. +type LogFunc func(ctx context.Context, message string, err error) + +// ErrCode is used for classification of different types of errors that may +// occur during validation. These may be used to write an appropriate response +// in ErrFunc. +type ErrCode int + +const ( + // ErrCodeOK indicates no error. It is also the default value. + ErrCodeOK = 0 + // ErrCodeCannotFindRoute happens when the validator fails to resolve the + // request to a defined OpenAPI route. + ErrCodeCannotFindRoute = iota + // ErrCodeRequestInvalid happens when the inbound request does not conform + // to the OpenAPI 3 specification. + ErrCodeRequestInvalid = iota + // ErrCodeResponseInvalid happens when the wrapped handler response does + // not conform to the OpenAPI 3 specification. + ErrCodeResponseInvalid = iota +) + +func (e ErrCode) responseText() string { + switch e { + case ErrCodeOK: + return "OK" + case ErrCodeCannotFindRoute: + return "not found" + case ErrCodeRequestInvalid: + return "bad request" + default: + return "server error" + } +} + +// NewValidator returns a new response validation middleware, using the given +// routes from an OpenAPI 3 specification. +func NewValidator(router routers.Router, options ...ValidatorOption) *Validator { + v := &Validator{ + router: router, + errFunc: func(_ context.Context, w http.ResponseWriter, status int, code ErrCode, _ error) { + http.Error(w, code.responseText(), status) + }, + logFunc: func(_ context.Context, message string, err error) { + log.Printf("%s: %v", message, err) + }, + } + for i := range options { + options[i](v) + } + return v +} + +// ValidatorOption defines an option that may be specified when creating a +// Validator. +type ValidatorOption func(*Validator) + +// OnErr provides a callback that handles writing an HTTP response on a +// validation error. This allows customization of error responses without +// prescribing a particular form. This callback is only called on response +// validator errors in Strict mode. +func OnErr(f ErrFunc) ValidatorOption { + return func(v *Validator) { + v.errFunc = f + } +} + +// OnLog provides a callback that handles logging in the Validator. This allows +// the validator to integrate with a services' existing logging system without +// prescribing a particular one. +func OnLog(f LogFunc) ValidatorOption { + return func(v *Validator) { + v.logFunc = f + } +} + +// Strict, if set, causes an internal server error to be sent if the wrapped +// handler response fails response validation. If not set, the response is sent +// and the error is only logged. +func Strict(strict bool) ValidatorOption { + return func(v *Validator) { + v.strict = strict + } +} + +// ValidationOptions sets request/response validation options on the validator. +func ValidationOptions(options Options) ValidatorOption { + return func(v *Validator) { + v.options = options + } +} + +// Middleware returns an http.Handler which wraps the given handler with +// request and response validation. +func (v *Validator) Middleware(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + route, pathParams, err := v.router.FindRoute(r) + if err != nil { + v.logFunc(ctx, "validation error: failed to find route for "+r.URL.String(), err) + v.errFunc(ctx, w, http.StatusNotFound, ErrCodeCannotFindRoute, err) + return + } + requestValidationInput := &RequestValidationInput{ + Request: r, + PathParams: pathParams, + Route: route, + Options: &v.options, + } + if err = ValidateRequest(ctx, requestValidationInput); err != nil { + v.logFunc(ctx, "invalid request", err) + v.errFunc(ctx, w, http.StatusBadRequest, ErrCodeRequestInvalid, err) + return + } + + var wr responseWrapper + if v.strict { + wr = &strictResponseWrapper{w: w} + } else { + wr = newWarnResponseWrapper(w) + } + + h.ServeHTTP(wr, r) + + if err = ValidateResponse(ctx, &ResponseValidationInput{ + RequestValidationInput: requestValidationInput, + Status: wr.statusCode(), + Header: wr.Header(), + Body: io.NopCloser(bytes.NewBuffer(wr.bodyContents())), + Options: &v.options, + }); err != nil { + v.logFunc(ctx, "invalid response", err) + if v.strict { + v.errFunc(ctx, w, http.StatusInternalServerError, ErrCodeResponseInvalid, err) + } + return + } + + if err = wr.flushBodyContents(); err != nil { + v.logFunc(ctx, "failed to write response", err) + } + }) +} + +type responseWrapper interface { + http.ResponseWriter + + // flushBodyContents writes the buffered response to the client, if it has + // not yet been written. + flushBodyContents() error + + // statusCode returns the response status code, 0 if not set yet. + statusCode() int + + // bodyContents returns the buffered + bodyContents() []byte +} + +type warnResponseWrapper struct { + w http.ResponseWriter + headerWritten bool + status int + body bytes.Buffer + tee io.Writer +} + +func newWarnResponseWrapper(w http.ResponseWriter) *warnResponseWrapper { + wr := &warnResponseWrapper{ + w: w, + } + wr.tee = io.MultiWriter(w, &wr.body) + return wr +} + +// Write implements http.ResponseWriter. +func (wr *warnResponseWrapper) Write(b []byte) (int, error) { + if !wr.headerWritten { + wr.WriteHeader(http.StatusOK) + } + return wr.tee.Write(b) +} + +// WriteHeader implements http.ResponseWriter. +func (wr *warnResponseWrapper) WriteHeader(status int) { + if !wr.headerWritten { + // If the header hasn't been written, record the status for response + // validation. + wr.status = status + wr.headerWritten = true + } + wr.w.WriteHeader(wr.status) +} + +// Header implements http.ResponseWriter. +func (wr *warnResponseWrapper) Header() http.Header { + return wr.w.Header() +} + +// Flush implements the optional http.Flusher interface. +func (wr *warnResponseWrapper) Flush() { + // If the wrapped http.ResponseWriter implements optional http.Flusher, + // pass through. + if fl, ok := wr.w.(http.Flusher); ok { + fl.Flush() + } +} + +func (wr *warnResponseWrapper) flushBodyContents() error { + return nil +} + +func (wr *warnResponseWrapper) statusCode() int { + return wr.status +} + +func (wr *warnResponseWrapper) bodyContents() []byte { + return wr.body.Bytes() +} + +type strictResponseWrapper struct { + w http.ResponseWriter + headerWritten bool + status int + body bytes.Buffer +} + +// Write implements http.ResponseWriter. +func (wr *strictResponseWrapper) Write(b []byte) (int, error) { + if !wr.headerWritten { + wr.WriteHeader(http.StatusOK) + } + return wr.body.Write(b) +} + +// WriteHeader implements http.ResponseWriter. +func (wr *strictResponseWrapper) WriteHeader(status int) { + if !wr.headerWritten { + wr.status = status + wr.headerWritten = true + } +} + +// Header implements http.ResponseWriter. +func (wr *strictResponseWrapper) Header() http.Header { + return wr.w.Header() +} + +func (wr *strictResponseWrapper) flushBodyContents() error { + wr.w.WriteHeader(wr.status) + _, err := wr.w.Write(wr.body.Bytes()) + return err +} + +func (wr *strictResponseWrapper) statusCode() int { + return wr.status +} + +func (wr *strictResponseWrapper) bodyContents() []byte { + return wr.body.Bytes() +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/options.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/options.go new file mode 100644 index 00000000..e7fad832 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/options.go @@ -0,0 +1,50 @@ +package openapi3filter + +import "github.com/getkin/kin-openapi/openapi3" + +// Options used by ValidateRequest and ValidateResponse +type Options struct { + // Set ExcludeRequestBody so ValidateRequest skips request body validation + ExcludeRequestBody bool + + // Set ExcludeRequestQueryParams so ValidateRequest skips request query params validation + ExcludeRequestQueryParams bool + + // Set ExcludeResponseBody so ValidateResponse skips response body validation + ExcludeResponseBody bool + + // Set ExcludeReadOnlyValidations so ValidateRequest skips read-only validations + ExcludeReadOnlyValidations bool + + // Set ExcludeWriteOnlyValidations so ValidateResponse skips write-only validations + ExcludeWriteOnlyValidations bool + + // Set IncludeResponseStatus so ValidateResponse fails on response + // status not defined in OpenAPI spec + IncludeResponseStatus bool + + MultiError bool + + // Set RegexCompiler to override the regex implementation + RegexCompiler openapi3.RegexCompilerFunc + + // A document with security schemes defined will not pass validation + // unless an AuthenticationFunc is defined. + // See NoopAuthenticationFunc + AuthenticationFunc AuthenticationFunc + + // Indicates whether default values are set in the + // request. If true, then they are not set + SkipSettingDefaults bool + + customSchemaErrorFunc CustomSchemaErrorFunc +} + +// CustomSchemaErrorFunc allows for custom the schema error message. +type CustomSchemaErrorFunc func(err *openapi3.SchemaError) string + +// WithCustomSchemaErrorFunc sets a function to override the schema error message. +// If the passed function returns an empty string, it returns to the previous Error() implementation. +func (o *Options) WithCustomSchemaErrorFunc(f CustomSchemaErrorFunc) { + o.customSchemaErrorFunc = f +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/req_resp_decoder.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/req_resp_decoder.go new file mode 100644 index 00000000..998a91f8 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/req_resp_decoder.go @@ -0,0 +1,1591 @@ +package openapi3filter + +import ( + "archive/zip" + "bytes" + "encoding/csv" + "encoding/json" + "errors" + "fmt" + "io" + "mime" + "mime/multipart" + "net/http" + "net/url" + "reflect" + "regexp" + "strconv" + "strings" + + "github.com/oasdiff/yaml3" + + "github.com/getkin/kin-openapi/openapi3" +) + +// ParseErrorKind describes a kind of ParseError. +// The type simplifies comparison of errors. +type ParseErrorKind int + +const ( + // KindOther describes an untyped parsing error. + KindOther ParseErrorKind = iota + // KindUnsupportedFormat describes an error that happens when a value has an unsupported format. + KindUnsupportedFormat + // KindInvalidFormat describes an error that happens when a value does not conform a format + // that is required by a serialization method. + KindInvalidFormat +) + +// ParseError describes errors which happens while parse operation's parameters, requestBody, or response. +type ParseError struct { + Kind ParseErrorKind + Value any + Reason string + Cause error + + path []any +} + +var _ interface{ Unwrap() error } = ParseError{} + +func (e *ParseError) Error() string { + var msg []string + if p := e.Path(); len(p) > 0 { + var arr []string + for _, v := range p { + arr = append(arr, fmt.Sprintf("%v", v)) + } + msg = append(msg, fmt.Sprintf("path %v", strings.Join(arr, "."))) + } + msg = append(msg, e.innerError()) + return strings.Join(msg, ": ") +} + +func (e *ParseError) innerError() string { + var msg []string + if e.Value != nil { + msg = append(msg, fmt.Sprintf("value %v", e.Value)) + } + if e.Reason != "" { + msg = append(msg, e.Reason) + } + if e.Cause != nil { + if v, ok := e.Cause.(*ParseError); ok { + msg = append(msg, v.innerError()) + } else { + msg = append(msg, e.Cause.Error()) + } + } + return strings.Join(msg, ": ") +} + +// RootCause returns a root cause of ParseError. +func (e *ParseError) RootCause() error { + if v, ok := e.Cause.(*ParseError); ok { + return v.RootCause() + } + return e.Cause +} + +func (e ParseError) Unwrap() error { + return e.Cause +} + +// Path returns a path to the root cause. +func (e *ParseError) Path() []any { + var path []any + if v, ok := e.Cause.(*ParseError); ok { + p := v.Path() + if len(p) > 0 { + path = append(path, p...) + } + } + if len(e.path) > 0 { + path = append(path, e.path...) + } + return path +} + +func invalidSerializationMethodErr(sm *openapi3.SerializationMethod) error { + return fmt.Errorf("invalid serialization method: style=%q, explode=%v", sm.Style, sm.Explode) +} + +// Decodes a parameter defined via the content property as an object. It uses +// the user specified decoder, or our build-in decoder for application/json +func decodeContentParameter(param *openapi3.Parameter, input *RequestValidationInput) ( + value any, + schema *openapi3.Schema, + found bool, + err error, +) { + var paramValues []string + switch param.In { + case openapi3.ParameterInPath: + var paramValue string + if paramValue, found = input.PathParams[param.Name]; found { + paramValues = []string{paramValue} + } + case openapi3.ParameterInQuery: + paramValues, found = input.GetQueryParams()[param.Name] + case openapi3.ParameterInHeader: + var headerValues []string + if headerValues, found = input.Request.Header[http.CanonicalHeaderKey(param.Name)]; found { + paramValues = headerValues + } + case openapi3.ParameterInCookie: + var cookie *http.Cookie + if cookie, err = input.Request.Cookie(param.Name); err == http.ErrNoCookie { + found = false + } else if err != nil { + return + } else { + paramValues = []string{cookie.Value} + found = true + } + default: + err = fmt.Errorf("unsupported parameter.in: %q", param.In) + return + } + + if !found { + if param.Required { + err = fmt.Errorf("parameter %q is required, but missing", param.Name) + } + return + } + + decoder := input.ParamDecoder + if decoder == nil { + decoder = defaultContentParameterDecoder + } + + value, schema, err = decoder(param, paramValues) + return +} + +func defaultContentParameterDecoder(param *openapi3.Parameter, values []string) ( + outValue any, + outSchema *openapi3.Schema, + err error, +) { + // Only query parameters can have multiple values. + if len(values) > 1 && param.In != openapi3.ParameterInQuery { + err = fmt.Errorf("%s parameter %q cannot have multiple values", param.In, param.Name) + return + } + + content := param.Content + if content == nil { + err = fmt.Errorf("parameter %q expected to have content", param.Name) + return + } + // We only know how to decode a parameter if it has one content, application/json + if len(content) != 1 { + err = fmt.Errorf("multiple content types for parameter %q", param.Name) + return + } + + mt := content.Get("application/json") + if mt == nil { + err = fmt.Errorf("parameter %q has no content schema", param.Name) + return + } + outSchema = mt.Schema.Value + + unmarshal := func(encoded string, paramSchema *openapi3.SchemaRef) (decoded any, err error) { + if err = json.Unmarshal([]byte(encoded), &decoded); err != nil { + if paramSchema != nil && !paramSchema.Value.Type.Is("object") { + decoded, err = encoded, nil + } + } + return + } + + if len(values) == 1 { + if outValue, err = unmarshal(values[0], mt.Schema); err != nil { + err = fmt.Errorf("error unmarshaling parameter %q", param.Name) + return + } + } else { + outArray := make([]any, 0, len(values)) + for _, v := range values { + var item any + if item, err = unmarshal(v, outSchema.Items); err != nil { + err = fmt.Errorf("error unmarshaling parameter %q", param.Name) + return + } + outArray = append(outArray, item) + } + outValue = outArray + } + return +} + +type valueDecoder interface { + DecodePrimitive(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) + DecodeArray(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) ([]any, bool, error) + DecodeObject(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (map[string]any, bool, error) +} + +// decodeStyledParameter returns a value of an operation's parameter from HTTP request for +// parameters defined using the style format, and whether the parameter is supplied in the input. +// The function returns ParseError when HTTP request contains an invalid value of a parameter. +func decodeStyledParameter(param *openapi3.Parameter, input *RequestValidationInput) (any, bool, error) { + sm, err := param.SerializationMethod() + if err != nil { + return nil, false, err + } + + var dec valueDecoder + switch param.In { + case openapi3.ParameterInPath: + if len(input.PathParams) == 0 { + return nil, false, nil + } + dec = &pathParamDecoder{pathParams: input.PathParams} + case openapi3.ParameterInQuery: + if len(input.GetQueryParams()) == 0 { + return nil, false, nil + } + dec = &urlValuesDecoder{values: input.GetQueryParams()} + case openapi3.ParameterInHeader: + dec = &headerParamDecoder{header: input.Request.Header} + case openapi3.ParameterInCookie: + dec = &cookieParamDecoder{req: input.Request} + default: + return nil, false, fmt.Errorf("unsupported parameter's 'in': %s", param.In) + } + + return decodeValue(dec, param.Name, sm, param.Schema, param.Required) +} + +func decodeValue(dec valueDecoder, param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef, required bool) (any, bool, error) { + var found bool + + if len(schema.Value.AllOf) > 0 { + var value any + var err error + for _, sr := range schema.Value.AllOf { + var f bool + value, f, err = decodeValue(dec, param, sm, sr, required) + found = found || f + if value == nil || err != nil { + break + } + } + return value, found, err + } + + if len(schema.Value.AnyOf) > 0 { + for _, sr := range schema.Value.AnyOf { + value, f, _ := decodeValue(dec, param, sm, sr, required) + found = found || f + if value != nil { + return value, found, nil + } + } + if required { + return nil, found, fmt.Errorf("decoding anyOf for parameter %q failed", param) + } + return nil, found, nil + } + + if len(schema.Value.OneOf) > 0 { + isMatched := 0 + var value any + for _, sr := range schema.Value.OneOf { + v, f, _ := decodeValue(dec, param, sm, sr, required) + found = found || f + if v != nil { + value = v + isMatched++ + } + } + if isMatched >= 1 { + return value, found, nil + } + if required { + return nil, found, fmt.Errorf("decoding oneOf failed: %q is required", param) + } + return nil, found, nil + } + + if schema.Value.Not != nil { + // TODO(decode not): handle decoding "not" JSON Schema + return nil, found, errors.New("not implemented: decoding 'not'") + } + + if schema.Value.Type != nil { + var decodeFn func(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) + switch { + case schema.Value.Type.Is("array"): + decodeFn = func(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) { + res, b, e := dec.DecodeArray(param, sm, schema) + if len(res) == 0 { + return nil, b, e + } + return res, b, e + } + case schema.Value.Type.Is("object"): + decodeFn = func(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) { + return dec.DecodeObject(param, sm, schema) + } + default: + decodeFn = dec.DecodePrimitive + } + return decodeFn(param, sm, schema) + } + switch vDecoder := dec.(type) { + case *pathParamDecoder: + _, found = vDecoder.pathParams[param] + case *urlValuesDecoder: + if schema.Value.Pattern != "" { + return dec.DecodePrimitive(param, sm, schema) + } + _, found = vDecoder.values[param] + case *headerParamDecoder: + _, found = vDecoder.header[http.CanonicalHeaderKey(param)] + case *cookieParamDecoder: + _, err := vDecoder.req.Cookie(param) + found = err != http.ErrNoCookie + default: + return nil, found, errors.New("unsupported decoder") + } + return nil, found, nil +} + +// pathParamDecoder decodes values of path parameters. +type pathParamDecoder struct { + pathParams map[string]string +} + +func (d *pathParamDecoder) DecodePrimitive(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) { + var prefix string + switch sm.Style { + case "simple": + // A prefix is empty for style "simple". + case "label": + prefix = "." + case "matrix": + prefix = ";" + param + "=" + default: + return nil, false, invalidSerializationMethodErr(sm) + } + + if d.pathParams == nil { + // HTTP request does not contains a value of the target path parameter. + return nil, false, nil + } + raw, ok := d.pathParams[param] + if !ok || raw == "" { + // HTTP request does not contains a value of the target path parameter. + return nil, false, nil + } + src, err := cutPrefix(raw, prefix) + if err != nil { + return nil, ok, err + } + val, err := parsePrimitive(src, schema) + return val, ok, err +} + +func (d *pathParamDecoder) DecodeArray(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) ([]any, bool, error) { + var prefix, delim string + switch { + case sm.Style == "simple": + delim = "," + case sm.Style == "label" && !sm.Explode: + prefix = "." + delim = "," + case sm.Style == "label" && sm.Explode: + prefix = "." + delim = "." + case sm.Style == "matrix" && !sm.Explode: + prefix = ";" + param + "=" + delim = "," + case sm.Style == "matrix" && sm.Explode: + prefix = ";" + param + "=" + delim = ";" + param + "=" + default: + return nil, false, invalidSerializationMethodErr(sm) + } + + if d.pathParams == nil { + // HTTP request does not contains a value of the target path parameter. + return nil, false, nil + } + raw, ok := d.pathParams[param] + if !ok || raw == "" { + // HTTP request does not contains a value of the target path parameter. + return nil, false, nil + } + src, err := cutPrefix(raw, prefix) + if err != nil { + return nil, ok, err + } + val, err := parseArray(strings.Split(src, delim), schema) + return val, ok, err +} + +func (d *pathParamDecoder) DecodeObject(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (map[string]any, bool, error) { + var prefix, propsDelim, valueDelim string + switch { + case sm.Style == "simple" && !sm.Explode: + propsDelim = "," + valueDelim = "," + case sm.Style == "simple" && sm.Explode: + propsDelim = "," + valueDelim = "=" + case sm.Style == "label" && !sm.Explode: + prefix = "." + propsDelim = "," + valueDelim = "," + case sm.Style == "label" && sm.Explode: + prefix = "." + propsDelim = "." + valueDelim = "=" + case sm.Style == "matrix" && !sm.Explode: + prefix = ";" + param + "=" + propsDelim = "," + valueDelim = "," + case sm.Style == "matrix" && sm.Explode: + prefix = ";" + propsDelim = ";" + valueDelim = "=" + default: + return nil, false, invalidSerializationMethodErr(sm) + } + + if d.pathParams == nil { + // HTTP request does not contains a value of the target path parameter. + return nil, false, nil + } + raw, ok := d.pathParams[param] + if !ok || raw == "" { + // HTTP request does not contains a value of the target path parameter. + return nil, false, nil + } + src, err := cutPrefix(raw, prefix) + if err != nil { + return nil, ok, err + } + props, err := propsFromString(src, propsDelim, valueDelim) + if err != nil { + return nil, ok, err + } + + val, err := makeObject(props, schema) + return val, ok, err +} + +// cutPrefix validates that a raw value of a path parameter has the specified prefix, +// and returns a raw value without the prefix. +func cutPrefix(raw, prefix string) (string, error) { + if prefix == "" { + return raw, nil + } + if len(raw) < len(prefix) || raw[:len(prefix)] != prefix { + return "", &ParseError{ + Kind: KindInvalidFormat, + Value: raw, + Reason: fmt.Sprintf("a value must be prefixed with %q", prefix), + } + } + return raw[len(prefix):], nil +} + +// urlValuesDecoder decodes values of query parameters. +type urlValuesDecoder struct { + values url.Values +} + +func (d *urlValuesDecoder) DecodePrimitive(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) { + if sm.Style != "form" { + return nil, false, invalidSerializationMethodErr(sm) + } + + values, ok := d.values[param] + if len(values) == 0 { + // HTTP request does not contain a value of the target query parameter. + return nil, ok, nil + } + + if schema.Value.Type == nil && schema.Value.Pattern != "" { + return values[0], ok, nil + } + val, err := parsePrimitive(values[0], schema) + return val, ok, err +} + +func (d *urlValuesDecoder) DecodeArray(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) ([]any, bool, error) { + if sm.Style == "deepObject" { + return nil, false, invalidSerializationMethodErr(sm) + } + + values, ok := d.values[param] + if len(values) == 0 { + // HTTP request does not contain a value of the target query parameter. + return nil, ok, nil + } + if !sm.Explode { + var delim string + switch sm.Style { + case "form": + delim = "," + case "spaceDelimited": + delim = " " + case "pipeDelimited": + delim = "|" + } + values = strings.Split(values[0], delim) + } + val, err := d.parseArray(values, sm, schema) + return val, ok, err +} + +// parseArray returns an array that contains items from a raw array. +// Every item is parsed as a primitive value. +// The function returns an error when an error happened while parse array's items. +func (d *urlValuesDecoder) parseArray(raw []string, sm *openapi3.SerializationMethod, schemaRef *openapi3.SchemaRef) ([]any, error) { + var value []any + + for i, v := range raw { + item, err := d.parseValue(v, schemaRef.Value.Items) + if err != nil { + if v, ok := err.(*ParseError); ok { + return nil, &ParseError{path: []any{i}, Cause: v} + } + return nil, fmt.Errorf("item %d: %w", i, err) + } + + // If the items are nil, then the array is nil. There shouldn't be case where some values are actual primitive + // values and some are nil values. + if item == nil { + return nil, nil + } + value = append(value, item) + } + return value, nil +} + +func (d *urlValuesDecoder) parseValue(v string, schema *openapi3.SchemaRef) (any, error) { + if len(schema.Value.AllOf) > 0 { + var value any + var err error + for _, sr := range schema.Value.AllOf { + value, err = d.parseValue(v, sr) + if value == nil || err != nil { + break + } + } + return value, err + } + + if len(schema.Value.AnyOf) > 0 { + var value any + var err error + for _, sr := range schema.Value.AnyOf { + if value, err = d.parseValue(v, sr); err == nil { + return value, nil + } + } + + return nil, err + } + + if len(schema.Value.OneOf) > 0 { + isMatched := 0 + var value any + var err error + for _, sr := range schema.Value.OneOf { + result, err := d.parseValue(v, sr) + if err == nil { + value = result + isMatched++ + } + } + if isMatched == 1 { + return value, nil + } else if isMatched > 1 { + return nil, fmt.Errorf("decoding oneOf failed: %d schemas matched", isMatched) + } else if isMatched == 0 { + return nil, fmt.Errorf("decoding oneOf failed: %d schemas matched", isMatched) + } + + return nil, err + } + + if schema.Value.Not != nil { + // TODO(decode not): handle decoding "not" JSON Schema + return nil, errors.New("not implemented: decoding 'not'") + } + + return parsePrimitive(v, schema) +} + +const ( + urlDecoderDelimiter = "\x1F" // should not conflict with URL characters +) + +func (d *urlValuesDecoder) DecodeObject(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (map[string]any, bool, error) { + var propsFn func(url.Values) (map[string]string, error) + switch sm.Style { + case "form": + propsFn = func(params url.Values) (map[string]string, error) { + if len(params) == 0 { + // HTTP request does not contain query parameters. + return nil, nil + } + if sm.Explode { + props := make(map[string]string) + for key, values := range params { + props[key] = values[0] + } + return props, nil + } + values := params[param] + if len(values) == 0 { + // HTTP request does not contain a value of the target query parameter. + return nil, nil + } + return propsFromString(values[0], ",", ",") + } + case "deepObject": + propsFn = func(params url.Values) (map[string]string, error) { + props := make(map[string]string) + for key, values := range params { + if !regexp.MustCompile(fmt.Sprintf(`^%s\[`, regexp.QuoteMeta(param))).MatchString(key) { + continue + } + + matches := regexp.MustCompile(`\[(.*?)\]`).FindAllStringSubmatch(key, -1) + switch l := len(matches); { + case l == 0: + // A query parameter's name does not match the required format, so skip it. + continue + case l >= 1: + kk := []string{} + for _, m := range matches { + kk = append(kk, m[1]) + } + props[strings.Join(kk, urlDecoderDelimiter)] = strings.Join(values, urlDecoderDelimiter) + } + } + if len(props) == 0 { + // HTTP request does not contain query parameters encoded by rules of style "deepObject". + return nil, nil + } + return props, nil + } + default: + return nil, false, invalidSerializationMethodErr(sm) + } + props, err := propsFn(d.values) + if err != nil { + return nil, false, err + } + if props == nil { + return nil, false, nil + } + val, err := makeObject(props, schema) + if err != nil { + return nil, false, err + } + + found := false + for propName := range schema.Value.Properties { + if _, ok := props[propName]; ok { + found = true + break + } + + if schema.Value.Type.Permits("array") || schema.Value.Type.Permits("object") { + for k := range props { + path := strings.Split(k, urlDecoderDelimiter) + if _, ok := deepGet(val, path...); ok { + found = true + break + } + } + } + } + + return val, found, nil +} + +// headerParamDecoder decodes values of header parameters. +type headerParamDecoder struct { + header http.Header +} + +func (d *headerParamDecoder) DecodePrimitive(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) { + if sm.Style != "simple" { + return nil, false, invalidSerializationMethodErr(sm) + } + + raw, ok := d.header[http.CanonicalHeaderKey(param)] + if !ok || len(raw) == 0 { + // HTTP request does not contains a corresponding header or has the empty value + return nil, ok, nil + } + + val, err := parsePrimitive(raw[0], schema) + return val, ok, err +} + +func (d *headerParamDecoder) DecodeArray(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) ([]any, bool, error) { + if sm.Style != "simple" { + return nil, false, invalidSerializationMethodErr(sm) + } + + raw, ok := d.header[http.CanonicalHeaderKey(param)] + if !ok || len(raw) == 0 { + // HTTP request does not contains a corresponding header + return nil, ok, nil + } + + val, err := parseArray(strings.Split(raw[0], ","), schema) + return val, ok, err +} + +func (d *headerParamDecoder) DecodeObject(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (map[string]any, bool, error) { + if sm.Style != "simple" { + return nil, false, invalidSerializationMethodErr(sm) + } + valueDelim := "," + if sm.Explode { + valueDelim = "=" + } + + raw, ok := d.header[http.CanonicalHeaderKey(param)] + if !ok || len(raw) == 0 { + // HTTP request does not contain a corresponding header. + return nil, ok, nil + } + props, err := propsFromString(raw[0], ",", valueDelim) + if err != nil { + return nil, ok, err + } + val, err := makeObject(props, schema) + return val, ok, err +} + +// cookieParamDecoder decodes values of cookie parameters. +type cookieParamDecoder struct { + req *http.Request +} + +func (d *cookieParamDecoder) DecodePrimitive(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (any, bool, error) { + if sm.Style != "form" { + return nil, false, invalidSerializationMethodErr(sm) + } + + cookie, err := d.req.Cookie(param) + found := err != http.ErrNoCookie + if !found { + // HTTP request does not contain a corresponding cookie. + return nil, found, nil + } + if err != nil { + return nil, found, fmt.Errorf("decoding param %q: %w", param, err) + } + + val, err := parsePrimitive(cookie.Value, schema) + return val, found, err +} + +func (d *cookieParamDecoder) DecodeArray(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) ([]any, bool, error) { + if sm.Style != "form" || sm.Explode { + return nil, false, invalidSerializationMethodErr(sm) + } + + cookie, err := d.req.Cookie(param) + found := err != http.ErrNoCookie + if !found { + // HTTP request does not contain a corresponding cookie. + return nil, found, nil + } + if err != nil { + return nil, found, fmt.Errorf("decoding param %q: %w", param, err) + } + val, err := parseArray(strings.Split(cookie.Value, ","), schema) + return val, found, err +} + +func (d *cookieParamDecoder) DecodeObject(param string, sm *openapi3.SerializationMethod, schema *openapi3.SchemaRef) (map[string]any, bool, error) { + if sm.Style != "form" || sm.Explode { + return nil, false, invalidSerializationMethodErr(sm) + } + + cookie, err := d.req.Cookie(param) + found := err != http.ErrNoCookie + if !found { + // HTTP request does not contain a corresponding cookie. + return nil, found, nil + } + if err != nil { + return nil, found, fmt.Errorf("decoding param %q: %w", param, err) + } + props, err := propsFromString(cookie.Value, ",", ",") + if err != nil { + return nil, found, err + } + val, err := makeObject(props, schema) + return val, found, err +} + +// propsFromString returns a properties map that is created by splitting a source string by propDelim and valueDelim. +// The source string must have a valid format: pairs separated by . +// The function returns an error when the source string has an invalid format. +func propsFromString(src, propDelim, valueDelim string) (map[string]string, error) { + props := make(map[string]string) + pairs := strings.Split(src, propDelim) + + // When propDelim and valueDelim is equal the source string follow the next rule: + // every even item of pairs is a properties's name, and the subsequent odd item is a property's value. + if propDelim == valueDelim { + // Taking into account the rule above, a valid source string must be splitted by propDelim + // to an array with an even number of items. + if len(pairs)%2 != 0 { + return nil, &ParseError{ + Kind: KindInvalidFormat, + Value: src, + Reason: fmt.Sprintf("a value must be a list of object's properties in format \"name%svalue\" separated by %s", valueDelim, propDelim), + } + } + for i := 0; i < len(pairs)/2; i++ { + props[pairs[i*2]] = pairs[i*2+1] + } + return props, nil + } + + // When propDelim and valueDelim is not equal the source string follow the next rule: + // every item of pairs is a string that follows format . + for _, pair := range pairs { + prop := strings.Split(pair, valueDelim) + if len(prop) != 2 { + return nil, &ParseError{ + Kind: KindInvalidFormat, + Value: src, + Reason: fmt.Sprintf("a value must be a list of object's properties in format \"name%svalue\" separated by %s", valueDelim, propDelim), + } + } + props[prop[0]] = prop[1] + } + return props, nil +} + +func deepGet(m map[string]any, keys ...string) (any, bool) { + for _, key := range keys { + val, ok := m[key] + if !ok { + return nil, false + } + if m, ok = val.(map[string]any); !ok { + return val, true + } + } + return m, true +} + +func deepSet(m map[string]any, keys []string, value any) { + for i := 0; i < len(keys)-1; i++ { + key := keys[i] + if _, ok := m[key]; !ok { + m[key] = make(map[string]any) + } + m = m[key].(map[string]any) + } + m[keys[len(keys)-1]] = value +} + +func findNestedSchema(parentSchema *openapi3.SchemaRef, keys []string) (*openapi3.SchemaRef, error) { + currentSchema := parentSchema + for _, key := range keys { + if currentSchema.Value.Type.Includes(openapi3.TypeArray) { + currentSchema = currentSchema.Value.Items + } else { + propertySchema, ok := currentSchema.Value.Properties[key] + if !ok { + if currentSchema.Value.AdditionalProperties.Schema == nil { + return nil, fmt.Errorf("nested schema for key %q not found", key) + } + currentSchema = currentSchema.Value.AdditionalProperties.Schema + continue + } + currentSchema = propertySchema + } + } + return currentSchema, nil +} + +// makeObject returns an object that contains properties from props. +func makeObject(props map[string]string, schema *openapi3.SchemaRef) (map[string]any, error) { + mobj := make(map[string]any) + + for kk, value := range props { + keys := strings.Split(kk, urlDecoderDelimiter) + if strings.Contains(value, urlDecoderDelimiter) { + // don't support implicit array indexes anymore + p := pathFromKeys(keys) + return nil, &ParseError{path: p, Kind: KindInvalidFormat, Reason: "array items must be set with indexes"} + } + deepSet(mobj, keys, value) + } + r, err := buildResObj(mobj, nil, "", schema) + if err != nil { + return nil, err + } + result, ok := r.(map[string]any) + if !ok { + return nil, &ParseError{Kind: KindOther, Reason: "invalid param object", Value: result} + } + + return result, nil +} + +// example: map[0:map[key:true] 1:map[key:false]] -> [map[key:true] map[key:false]] +func sliceMapToSlice(m map[string]any) ([]any, error) { + var result []any + + keys := make([]int, 0, len(m)) + for k := range m { + key, err := strconv.Atoi(k) + if err != nil { + return nil, fmt.Errorf("array indexes must be integers: %w", err) + } + keys = append(keys, key) + } + max := -1 + for _, k := range keys { + if k > max { + max = k + } + } + for i := 0; i <= max; i++ { + val, ok := m[strconv.Itoa(i)] + if !ok { + result = append(result, nil) + continue + } + result = append(result, val) + } + return result, nil +} + +// buildResObj constructs an object based on a given schema and param values +func buildResObj(params map[string]any, parentKeys []string, key string, schema *openapi3.SchemaRef) (any, error) { + mapKeys := parentKeys + if key != "" { + mapKeys = append(mapKeys, key) + } + + switch { + case schema.Value.Type.Is("array"): + paramArr, ok := deepGet(params, mapKeys...) + if !ok { + return nil, nil + } + t, isMap := paramArr.(map[string]any) + if !isMap { + return nil, &ParseError{path: pathFromKeys(mapKeys), Kind: KindInvalidFormat, Reason: "array items must be set with indexes"} + } + // intermediate arrays have to be instantiated + arr, err := sliceMapToSlice(t) + if err != nil { + return nil, &ParseError{path: pathFromKeys(mapKeys), Kind: KindInvalidFormat, Reason: fmt.Sprintf("could not convert value map to array: %v", err)} + } + resultArr := make([]any /*not 0,*/, len(arr)) + for i := range arr { + r, err := buildResObj(params, mapKeys, strconv.Itoa(i), schema.Value.Items) + if err != nil { + return nil, err + } + if r != nil { + resultArr[i] = r + } + } + return resultArr, nil + case schema.Value.Type.Is("object"): + resultMap := make(map[string]any) + additPropsSchema := schema.Value.AdditionalProperties.Schema + pp, _ := deepGet(params, mapKeys...) + objectParams, ok := pp.(map[string]any) + if !ok { + // not the expected type, but return it either way and leave validation up to ValidateParameter + return pp, nil + } + for k, propSchema := range schema.Value.Properties { + r, err := buildResObj(params, mapKeys, k, propSchema) + if err != nil { + return nil, err + } + if r != nil { + resultMap[k] = r + } + } + if additPropsSchema != nil { + // dynamic creation of possibly nested objects + for k := range objectParams { + r, err := buildResObj(params, mapKeys, k, additPropsSchema) + if err != nil { + return nil, err + } + if r != nil { + resultMap[k] = r + } + } + } + + return resultMap, nil + case len(schema.Value.AnyOf) > 0: + return buildFromSchemas(schema.Value.AnyOf, params, parentKeys, key) + case len(schema.Value.OneOf) > 0: + return buildFromSchemas(schema.Value.OneOf, params, parentKeys, key) + case len(schema.Value.AllOf) > 0: + return buildFromSchemas(schema.Value.AllOf, params, parentKeys, key) + default: + val, ok := deepGet(params, mapKeys...) + if !ok { + // leave validation up to ValidateParameter. here there really is not parameter set + return nil, nil + } + v, ok := val.(string) + if !ok { + return nil, &ParseError{path: pathFromKeys(mapKeys), Kind: KindInvalidFormat, Value: val, Reason: "path is not convertible to primitive"} + } + prim, err := parsePrimitive(v, schema) + if err != nil { + return nil, handlePropParseError(mapKeys, err) + } + + return prim, nil + } +} + +// buildFromSchemas decodes params with anyOf, oneOf, allOf schemas. +func buildFromSchemas(schemas openapi3.SchemaRefs, params map[string]any, mapKeys []string, key string) (any, error) { + resultMap := make(map[string]any) + for _, s := range schemas { + val, err := buildResObj(params, mapKeys, key, s) + if err == nil && val != nil { + + if m, ok := val.(map[string]any); ok { + for k, v := range m { + resultMap[k] = v + } + continue + } + + if a, ok := val.([]any); ok { + if len(a) > 0 { + return a, nil + } + continue + } + + // if its a primitive and not nil just return that and let it be validated + return val, nil + } + } + + if len(resultMap) > 0 { + return resultMap, nil + } + + return nil, nil +} + +func handlePropParseError(path []string, err error) error { + if v, ok := err.(*ParseError); ok { + return &ParseError{path: pathFromKeys(path), Cause: v} + } + return fmt.Errorf("property %q: %w", strings.Join(path, "."), err) +} + +func pathFromKeys(kk []string) []any { + path := make([]any, 0, len(kk)) + for _, v := range kk { + path = append(path, v) + } + return path +} + +// parseArray returns an array that contains items from a raw array. +// Every item is parsed as a primitive value. +// The function returns an error when an error happened while parse array's items. +func parseArray(raw []string, schemaRef *openapi3.SchemaRef) ([]any, error) { + var value []any + for i, v := range raw { + item, err := parsePrimitive(v, schemaRef.Value.Items) + if err != nil { + if v, ok := err.(*ParseError); ok { + return nil, &ParseError{path: []any{i}, Cause: v} + } + return nil, fmt.Errorf("item %d: %w", i, err) + } + + // If the items are nil, then the array is nil. There shouldn't be case where some values are actual primitive + // values and some are nil values. + if item == nil { + return nil, nil + } + value = append(value, item) + } + return value, nil +} + +// parsePrimitive returns a value that is created by parsing a source string to a primitive type +// that is specified by a schema. The function returns nil when the source string is empty. +// The function panics when a schema has a non-primitive type. +func parsePrimitive(raw string, schema *openapi3.SchemaRef) (v any, err error) { + if raw == "" { + return nil, nil + } + for _, typ := range schema.Value.Type.Slice() { + if v, err = parsePrimitiveCase(raw, schema, typ); err == nil { + return + } + } + return +} + +func parsePrimitiveCase(raw string, schema *openapi3.SchemaRef, typ string) (any, error) { + switch typ { + case "integer": + if schema.Value.Format == "int32" { + v, err := strconv.ParseInt(raw, 0, 32) + if err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Value: raw, Reason: "an invalid " + typ, Cause: err.(*strconv.NumError).Err} + } + return int32(v), nil + } + v, err := strconv.ParseInt(raw, 0, 64) + if err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Value: raw, Reason: "an invalid " + typ, Cause: err.(*strconv.NumError).Err} + } + return v, nil + case "number": + v, err := strconv.ParseFloat(raw, 64) + if err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Value: raw, Reason: "an invalid " + typ, Cause: err.(*strconv.NumError).Err} + } + return v, nil + case "boolean": + v, err := strconv.ParseBool(raw) + if err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Value: raw, Reason: "an invalid " + typ, Cause: err.(*strconv.NumError).Err} + } + return v, nil + case "string": + return raw, nil + default: + return nil, &ParseError{Kind: KindOther, Value: raw, Reason: "schema has non primitive type " + typ} + } +} + +// EncodingFn is a function that returns an encoding of a request body's part. +type EncodingFn func(partName string) *openapi3.Encoding + +// BodyDecoder is an interface to decode a body of a request or response. +// An implementation must return a value that is a primitive, []any, or map[string]any. +type BodyDecoder func(io.Reader, http.Header, *openapi3.SchemaRef, EncodingFn) (any, error) + +// bodyDecoders contains decoders for supported content types of a body. +// By default, there is content type "application/json" is supported only. +var bodyDecoders = make(map[string]BodyDecoder) + +// RegisteredBodyDecoder returns the registered body decoder for the given content type. +// +// If no decoder was registered for the given content type, nil is returned. +// This call is not thread-safe: body decoders should not be created/destroyed by multiple goroutines. +func RegisteredBodyDecoder(contentType string) BodyDecoder { + return bodyDecoders[contentType] +} + +// RegisterBodyDecoder registers a request body's decoder for a content type. +// +// If a decoder for the specified content type already exists, the function replaces +// it with the specified decoder. +// This call is not thread-safe: body decoders should not be created/destroyed by multiple goroutines. +func RegisterBodyDecoder(contentType string, decoder BodyDecoder) { + if contentType == "" { + panic("contentType is empty") + } + if decoder == nil { + panic("decoder is not defined") + } + bodyDecoders[contentType] = decoder +} + +// UnregisterBodyDecoder dissociates a body decoder from a content type. +// +// Decoding this content type will result in an error. +// This call is not thread-safe: body decoders should not be created/destroyed by multiple goroutines. +func UnregisterBodyDecoder(contentType string) { + if contentType == "" { + panic("contentType is empty") + } + delete(bodyDecoders, contentType) +} + +var headerCT = http.CanonicalHeaderKey("Content-Type") + +const prefixUnsupportedCT = "unsupported content type" + +// decodeBody returns a decoded body. +// The function returns ParseError when a body is invalid. +func decodeBody(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) ( + string, + any, + error, +) { + contentType := header.Get(headerCT) + if contentType == "" { + if _, ok := body.(*multipart.Part); ok { + contentType = "text/plain" + } + } + mediaType := parseMediaType(contentType) + decoder, ok := bodyDecoders[mediaType] + if !ok { + return "", nil, &ParseError{ + Kind: KindUnsupportedFormat, + Reason: fmt.Sprintf("%s %q", prefixUnsupportedCT, mediaType), + } + } + value, err := decoder(body, header, schema, encFn) + if err != nil { + return "", nil, err + } + return mediaType, value, nil +} + +func init() { + RegisterBodyDecoder("application/json", JSONBodyDecoder) + RegisterBodyDecoder("application/json-patch+json", JSONBodyDecoder) + RegisterBodyDecoder("application/ld+json", JSONBodyDecoder) + RegisterBodyDecoder("application/hal+json", JSONBodyDecoder) + RegisterBodyDecoder("application/vnd.api+json", JSONBodyDecoder) + RegisterBodyDecoder("application/octet-stream", FileBodyDecoder) + RegisterBodyDecoder("application/problem+json", JSONBodyDecoder) + RegisterBodyDecoder("application/x-www-form-urlencoded", urlencodedBodyDecoder) + RegisterBodyDecoder("application/x-yaml", yamlBodyDecoder) + RegisterBodyDecoder("application/yaml", yamlBodyDecoder) + RegisterBodyDecoder("application/zip", zipFileBodyDecoder) + RegisterBodyDecoder("multipart/form-data", multipartBodyDecoder) + RegisterBodyDecoder("text/csv", csvBodyDecoder) + RegisterBodyDecoder("text/plain", plainBodyDecoder) +} + +func plainBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + data, err := io.ReadAll(body) + if err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Cause: err} + } + return string(data), nil +} + +// JSONBodyDecoder decodes a JSON formatted body. It is public so that is easy +// to register additional JSON based formats. +func JSONBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + var value any + dec := json.NewDecoder(body) + dec.UseNumber() + if err := dec.Decode(&value); err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Cause: err} + } + return value, nil +} + +func yamlBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + var value any + if err := yaml.NewDecoder(body).Decode(&value); err != nil { + return nil, &ParseError{Kind: KindInvalidFormat, Cause: err} + } + return value, nil +} + +func urlencodedBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + // Validate schema of request body. + // By the OpenAPI 3 specification request body's schema must have type "object". + // Properties of the schema describes individual parts of request body. + if !schema.Value.Type.Is("object") { + return nil, errors.New("unsupported schema of request body") + } + for propName, propSchema := range schema.Value.Properties { + propType := propSchema.Value.Type + switch { + case propType.Is("object"): + return nil, fmt.Errorf("unsupported schema of request body's property %q", propName) + case propType.Is("array"): + items := propSchema.Value.Items.Value + if !(items.Type.Is("string") || items.Type.Is("integer") || items.Type.Is("number") || items.Type.Is("boolean")) { + return nil, fmt.Errorf("unsupported schema of request body's property %q", propName) + } + } + } + + // Parse form. + b, err := io.ReadAll(body) + if err != nil { + return nil, err + } + values, err := url.ParseQuery(string(b)) + if err != nil { + return nil, err + } + + // Make an object value from form values. + obj := make(map[string]any) + dec := &urlValuesDecoder{values: values} + + if err := decodeSchemaConstructs(dec, []*openapi3.SchemaRef{schema}, obj, encFn); err != nil { + return nil, err + } + + return obj, nil +} + +// decodeSchemaConstructs tries to decode properties based on provided schemas. +// This function is for decoding purposes only and not for validation. +func decodeSchemaConstructs(dec *urlValuesDecoder, schemas []*openapi3.SchemaRef, obj map[string]any, encFn EncodingFn) error { + for _, schemaRef := range schemas { + + // Decode schema constructs (allOf, anyOf, oneOf) + if err := decodeSchemaConstructs(dec, schemaRef.Value.AllOf, obj, encFn); err != nil { + return err + } + if err := decodeSchemaConstructs(dec, schemaRef.Value.AnyOf, obj, encFn); err != nil { + return err + } + if err := decodeSchemaConstructs(dec, schemaRef.Value.OneOf, obj, encFn); err != nil { + return err + } + + for name, prop := range schemaRef.Value.Properties { + value, _, err := decodeProperty(dec, name, prop, encFn) + if err != nil { + continue + } + if existingValue, exists := obj[name]; exists && !isEqual(existingValue, value) { + return fmt.Errorf("conflicting values for property %q", name) + } + obj[name] = value + } + } + + return nil +} + +func isEqual(value1, value2 any) bool { + return reflect.DeepEqual(value1, value2) +} + +func decodeProperty(dec valueDecoder, name string, prop *openapi3.SchemaRef, encFn EncodingFn) (any, bool, error) { + var enc *openapi3.Encoding + if encFn != nil { + enc = encFn(name) + } + sm := enc.SerializationMethod() + return decodeValue(dec, name, sm, prop, false) +} + +func multipartBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + if !schema.Value.Type.Is("object") { + return nil, errors.New("unsupported schema of request body") + } + + // Parse form. + values := make(map[string][]any) + contentType := header.Get(headerCT) + _, params, err := mime.ParseMediaType(contentType) + if err != nil { + return nil, err + } + mr := multipart.NewReader(body, params["boundary"]) + for { + var part *multipart.Part + if part, err = mr.NextPart(); err == io.EOF { + break + } + if err != nil { + return nil, err + } + + var ( + name = part.FormName() + enc *openapi3.Encoding + ) + if encFn != nil { + enc = encFn(name) + } + subEncFn := func(string) *openapi3.Encoding { return enc } + + var valueSchema *openapi3.SchemaRef + if len(schema.Value.AllOf) > 0 { + var exists bool + for _, sr := range schema.Value.AllOf { + if valueSchema, exists = sr.Value.Properties[name]; exists { + break + } + } + if !exists { + return nil, &ParseError{Kind: KindOther, Cause: fmt.Errorf("part %s: undefined", name)} + } + } else { + // If the property's schema has type "array" it is means that the form contains a few parts with the same name. + // Every such part has a type that is defined by an items schema in the property's schema. + var exists bool + if valueSchema, exists = schema.Value.Properties[name]; !exists { + if anyProperties := schema.Value.AdditionalProperties.Has; anyProperties != nil { + switch *anyProperties { + case true: + // additionalProperties: true + continue + default: + // additionalProperties: false + return nil, &ParseError{Kind: KindOther, Cause: fmt.Errorf("part %s: undefined", name)} + } + } + if schema.Value.AdditionalProperties.Schema == nil { + return nil, &ParseError{Kind: KindOther, Cause: fmt.Errorf("part %s: undefined", name)} + } + if valueSchema, exists = schema.Value.AdditionalProperties.Schema.Value.Properties[name]; !exists { + return nil, &ParseError{Kind: KindOther, Cause: fmt.Errorf("part %s: undefined", name)} + } + } + if valueSchema.Value.Type.Is("array") { + valueSchema = valueSchema.Value.Items + } + } + + var value any + if _, value, err = decodeBody(part, http.Header(part.Header), valueSchema, subEncFn); err != nil { + if v, ok := err.(*ParseError); ok { + return nil, &ParseError{path: []any{name}, Cause: v} + } + return nil, fmt.Errorf("part %s: %w", name, err) + } + values[name] = append(values[name], value) + } + + allTheProperties := make(map[string]*openapi3.SchemaRef) + if len(schema.Value.AllOf) > 0 { + for _, sr := range schema.Value.AllOf { + for k, v := range sr.Value.Properties { + allTheProperties[k] = v + } + if addProps := sr.Value.AdditionalProperties.Schema; addProps != nil { + for k, v := range addProps.Value.Properties { + allTheProperties[k] = v + } + } + } + } else { + for k, v := range schema.Value.Properties { + allTheProperties[k] = v + } + if addProps := schema.Value.AdditionalProperties.Schema; addProps != nil { + for k, v := range addProps.Value.Properties { + allTheProperties[k] = v + } + } + } + + // Make an object value from form values. + obj := make(map[string]any) + for name, prop := range allTheProperties { + vv := values[name] + if len(vv) == 0 { + continue + } + if prop.Value.Type.Is("array") { + obj[name] = vv + } else { + obj[name] = vv[0] + } + } + + return obj, nil +} + +// FileBodyDecoder is a body decoder that decodes a file body to a string. +func FileBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + data, err := io.ReadAll(body) + if err != nil { + return nil, err + } + return string(data), nil +} + +// zipFileBodyDecoder is a body decoder that decodes a zip file body to a string. +func zipFileBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + buff := bytes.NewBuffer([]byte{}) + size, err := io.Copy(buff, body) + if err != nil { + return nil, err + } + + zr, err := zip.NewReader(bytes.NewReader(buff.Bytes()), size) + if err != nil { + return nil, err + } + + const bufferSize = 256 + content := make([]byte, 0, bufferSize*len(zr.File)) + buffer := make([]byte /*0,*/, bufferSize) + + for _, f := range zr.File { + err := func() error { + rc, err := f.Open() + if err != nil { + return err + } + defer func() { + _ = rc.Close() + }() + + for { + n, err := rc.Read(buffer) + if 0 < n { + content = append(content, buffer...) + } + if err == io.EOF { + break + } + if err != nil { + return err + } + } + + return nil + }() + if err != nil { + return nil, err + } + } + + return string(content), nil +} + +// csvBodyDecoder is a body decoder that decodes a csv body to a string. +func csvBodyDecoder(body io.Reader, header http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (any, error) { + r := csv.NewReader(body) + + var sb strings.Builder + for { + record, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + + sb.WriteString(strings.Join(record, ",")) + sb.WriteString("\n") + } + + return sb.String(), nil +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/req_resp_encoder.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/req_resp_encoder.go new file mode 100644 index 00000000..5c328c75 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/req_resp_encoder.go @@ -0,0 +1,58 @@ +package openapi3filter + +import ( + "encoding/json" + "fmt" + "sync" +) + +func encodeBody(body any, mediaType string) ([]byte, error) { + if encoder := RegisteredBodyEncoder(mediaType); encoder != nil { + return encoder(body) + } + return nil, &ParseError{ + Kind: KindUnsupportedFormat, + Reason: fmt.Sprintf("%s %q", prefixUnsupportedCT, mediaType), + } +} + +// BodyEncoder really is an (encoding/json).Marshaler +type BodyEncoder func(body any) ([]byte, error) + +var bodyEncodersM sync.RWMutex +var bodyEncoders = map[string]BodyEncoder{ + "application/json": json.Marshal, +} + +// RegisterBodyEncoder enables package-wide decoding of contentType values +func RegisterBodyEncoder(contentType string, encoder BodyEncoder) { + if contentType == "" { + panic("contentType is empty") + } + if encoder == nil { + panic("encoder is not defined") + } + bodyEncodersM.Lock() + bodyEncoders[contentType] = encoder + bodyEncodersM.Unlock() +} + +// UnregisterBodyEncoder disables package-wide decoding of contentType values +func UnregisterBodyEncoder(contentType string) { + if contentType == "" { + panic("contentType is empty") + } + bodyEncodersM.Lock() + delete(bodyEncoders, contentType) + bodyEncodersM.Unlock() +} + +// RegisteredBodyEncoder returns the registered body encoder for the given content type. +// +// If no encoder was registered for the given content type, nil is returned. +func RegisteredBodyEncoder(contentType string) BodyEncoder { + bodyEncodersM.RLock() + mayBE := bodyEncoders[contentType] + bodyEncodersM.RUnlock() + return mayBE +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_request.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_request.go new file mode 100644 index 00000000..a28fbccd --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_request.go @@ -0,0 +1,431 @@ +package openapi3filter + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "sort" + + "github.com/getkin/kin-openapi/openapi3" +) + +// ErrAuthenticationServiceMissing is returned when no authentication service +// is defined for the request validator +var ErrAuthenticationServiceMissing = errors.New("missing AuthenticationFunc") + +// ErrInvalidRequired is returned when a required value of a parameter or request body is not defined. +var ErrInvalidRequired = errors.New("value is required but missing") + +// ErrInvalidEmptyValue is returned when a value of a parameter or request body is empty while it's not allowed. +var ErrInvalidEmptyValue = errors.New("empty value is not allowed") + +// ValidateRequest is used to validate the given input according to previous +// loaded OpenAPIv3 spec. If the input does not match the OpenAPIv3 spec, a +// non-nil error will be returned. +// +// Note: One can tune the behavior of uniqueItems: true verification +// by registering a custom function with openapi3.RegisterArrayUniqueItemsChecker +func ValidateRequest(ctx context.Context, input *RequestValidationInput) error { + var me openapi3.MultiError + + options := input.Options + if options == nil { + options = &Options{} + } + route := input.Route + operation := route.Operation + operationParameters := operation.Parameters + pathItemParameters := route.PathItem.Parameters + + // Security + security := operation.Security + // If there aren't any security requirements for the operation + if security == nil { + // Use the global security requirements. + security = &route.Spec.Security + } + if security != nil { + if err := ValidateSecurityRequirements(ctx, input, *security); err != nil { + if !options.MultiError { + return err + } + me = append(me, err) + } + } + + // For each parameter of the PathItem + for _, parameterRef := range pathItemParameters { + parameter := parameterRef.Value + if operationParameters != nil { + if override := operationParameters.GetByInAndName(parameter.In, parameter.Name); override != nil { + continue + } + } + + if err := ValidateParameter(ctx, input, parameter); err != nil { + if !options.MultiError { + return err + } + me = append(me, err) + } + } + + // For each parameter of the Operation + for _, parameter := range operationParameters { + if options.ExcludeRequestQueryParams && parameter.Value.In == openapi3.ParameterInQuery { + continue + } + if err := ValidateParameter(ctx, input, parameter.Value); err != nil { + if !options.MultiError { + return err + } + me = append(me, err) + } + } + + // RequestBody + requestBody := operation.RequestBody + if requestBody != nil && !options.ExcludeRequestBody { + if err := ValidateRequestBody(ctx, input, requestBody.Value); err != nil { + if !options.MultiError { + return err + } + me = append(me, err) + } + } + + if len(me) > 0 { + return me + } + return nil +} + +// appendToQueryValues adds to query parameters each value in the provided slice +func appendToQueryValues[T any](q url.Values, parameterName string, v []T) { + for _, i := range v { + q.Add(parameterName, fmt.Sprintf("%v", i)) + } +} + +// populateDefaultQueryParameters populates default values inside query parameters, while ensuring types are respected +func populateDefaultQueryParameters(q url.Values, parameterName string, value any) { + switch t := value.(type) { + case []any: + appendToQueryValues(q, parameterName, t) + default: + q.Add(parameterName, fmt.Sprintf("%v", value)) + } + +} + +// ValidateParameter validates a parameter's value by JSON schema. +// The function returns RequestError with a ParseError cause when unable to parse a value. +// The function returns RequestError with ErrInvalidRequired cause when a value of a required parameter is not defined. +// The function returns RequestError with ErrInvalidEmptyValue cause when a value of a required parameter is not defined. +// The function returns RequestError with a openapi3.SchemaError cause when a value is invalid by JSON schema. +func ValidateParameter(ctx context.Context, input *RequestValidationInput, parameter *openapi3.Parameter) error { + if parameter.Schema == nil && parameter.Content == nil { + // We have no schema for the parameter. Assume that everything passes + // a schema-less check, but this could also be an error. The OpenAPI + // validation allows this to happen. + return nil + } + + options := input.Options + if options == nil { + options = &Options{} + } + + var value any + var err error + var found bool + var schema *openapi3.Schema + + // Validation will ensure that we either have content or schema. + if parameter.Content != nil { + if value, schema, found, err = decodeContentParameter(parameter, input); err != nil { + return &RequestError{Input: input, Parameter: parameter, Err: err} + } + } else { + if value, found, err = decodeStyledParameter(parameter, input); err != nil { + return &RequestError{Input: input, Parameter: parameter, Err: err} + } + schema = parameter.Schema.Value + } + + // Set default value if needed + if !options.SkipSettingDefaults && value == nil && schema != nil { + value = schema.Default + for _, subSchema := range schema.AllOf { + if subSchema.Value.Default != nil { + value = subSchema.Value.Default + break // This is not a validation of the schema itself, so use the first default value. + } + } + + if value != nil { + req := input.Request + switch parameter.In { + case openapi3.ParameterInPath: + // Path parameters are required. + // Next check `parameter.Required && !found` will catch this. + case openapi3.ParameterInQuery: + q := req.URL.Query() + populateDefaultQueryParameters(q, parameter.Name, value) + req.URL.RawQuery = q.Encode() + case openapi3.ParameterInHeader: + req.Header.Add(parameter.Name, fmt.Sprintf("%v", value)) + case openapi3.ParameterInCookie: + req.AddCookie(&http.Cookie{ + Name: parameter.Name, + Value: fmt.Sprintf("%v", value), + }) + } + } + } + + // Validate a parameter's value and presence. + if parameter.Required && !found { + return &RequestError{Input: input, Parameter: parameter, Reason: ErrInvalidRequired.Error(), Err: ErrInvalidRequired} + } + + if isNilValue(value) { + if !parameter.AllowEmptyValue && found { + return &RequestError{Input: input, Parameter: parameter, Reason: ErrInvalidEmptyValue.Error(), Err: ErrInvalidEmptyValue} + } + return nil + } + if schema == nil { + // A parameter's schema is not defined so skip validation of a parameter's value. + return nil + } + + var opts []openapi3.SchemaValidationOption + if options.MultiError { + opts = make([]openapi3.SchemaValidationOption, 0, 1) + opts = append(opts, openapi3.MultiErrors()) + } + if options.customSchemaErrorFunc != nil { + opts = append(opts, openapi3.SetSchemaErrorMessageCustomizer(options.customSchemaErrorFunc)) + } + if err = schema.VisitJSON(value, opts...); err != nil { + return &RequestError{Input: input, Parameter: parameter, Err: err} + } + return nil +} + +const prefixInvalidCT = "header Content-Type has unexpected value" + +// ValidateRequestBody validates data of a request's body. +// +// The function returns RequestError with ErrInvalidRequired cause when a value is required but not defined. +// The function returns RequestError with a openapi3.SchemaError cause when a value is invalid by JSON schema. +func ValidateRequestBody(ctx context.Context, input *RequestValidationInput, requestBody *openapi3.RequestBody) error { + var ( + req = input.Request + data []byte + ) + + options := input.Options + if options == nil { + options = &Options{} + } + + if req.Body != http.NoBody && req.Body != nil { + defer req.Body.Close() + var err error + if data, err = io.ReadAll(req.Body); err != nil { + return &RequestError{ + Input: input, + RequestBody: requestBody, + Reason: "reading failed", + Err: err, + } + } + // Put the data back into the input + req.Body = nil + if req.GetBody != nil { + if req.Body, err = req.GetBody(); err != nil { + req.Body = nil + } + } + if req.Body == nil { + req.ContentLength = int64(len(data)) + req.GetBody = func() (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader(data)), nil + } + req.Body, _ = req.GetBody() // no error return + } + } + + if len(data) == 0 { + if requestBody.Required { + return &RequestError{Input: input, RequestBody: requestBody, Err: ErrInvalidRequired} + } + return nil + } + + content := requestBody.Content + if len(content) == 0 { + // A request's body does not have declared content, so skip validation. + return nil + } + + inputMIME := req.Header.Get(headerCT) + contentType := requestBody.Content.Get(inputMIME) + if contentType == nil { + return &RequestError{ + Input: input, + RequestBody: requestBody, + Reason: fmt.Sprintf("%s %q", prefixInvalidCT, inputMIME), + } + } + + if contentType.Schema == nil { + // A JSON schema that describes the received data is not declared, so skip validation. + return nil + } + + encFn := func(name string) *openapi3.Encoding { return contentType.Encoding[name] } + mediaType, value, err := decodeBody(bytes.NewReader(data), req.Header, contentType.Schema, encFn) + if err != nil { + return &RequestError{ + Input: input, + RequestBody: requestBody, + Reason: "failed to decode request body", + Err: err, + } + } + + defaultsSet := false + opts := make([]openapi3.SchemaValidationOption, 0, 4) // 4 potential opts here + opts = append(opts, openapi3.VisitAsRequest()) + if !options.SkipSettingDefaults { + opts = append(opts, openapi3.DefaultsSet(func() { defaultsSet = true })) + } + if options.MultiError { + opts = append(opts, openapi3.MultiErrors()) + } + if options.customSchemaErrorFunc != nil { + opts = append(opts, openapi3.SetSchemaErrorMessageCustomizer(options.customSchemaErrorFunc)) + } + if options.ExcludeReadOnlyValidations { + opts = append(opts, openapi3.DisableReadOnlyValidation()) + } + if options.RegexCompiler != nil { + opts = append(opts, openapi3.SetSchemaRegexCompiler(options.RegexCompiler)) + } + + // Validate JSON with the schema + if err := contentType.Schema.Value.VisitJSON(value, opts...); err != nil { + schemaId := getSchemaIdentifier(contentType.Schema) + schemaId = prependSpaceIfNeeded(schemaId) + return &RequestError{ + Input: input, + RequestBody: requestBody, + Reason: fmt.Sprintf("doesn't match schema%s", schemaId), + Err: err, + } + } + + if defaultsSet { + var err error + if data, err = encodeBody(value, mediaType); err != nil { + return &RequestError{ + Input: input, + RequestBody: requestBody, + Reason: "rewriting failed", + Err: err, + } + } + // Put the data back into the input + if req.Body != nil { + req.Body.Close() + } + req.ContentLength = int64(len(data)) + req.GetBody = func() (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader(data)), nil + } + req.Body, _ = req.GetBody() // no error return + } + + return nil +} + +// ValidateSecurityRequirements goes through multiple OpenAPI 3 security +// requirements in order and returns nil on the first valid requirement. +// If no requirement is met, errors are returned in order. +func ValidateSecurityRequirements(ctx context.Context, input *RequestValidationInput, srs openapi3.SecurityRequirements) error { + if len(srs) == 0 { + return nil + } + var errs []error + for _, sr := range srs { + if err := validateSecurityRequirement(ctx, input, sr); err != nil { + if len(errs) == 0 { + errs = make([]error, 0, len(srs)) + } + errs = append(errs, err) + continue + } + return nil + } + return &SecurityRequirementsError{ + SecurityRequirements: srs, + Errors: errs, + } +} + +// validateSecurityRequirement validates a single OpenAPI 3 security requirement +func validateSecurityRequirement(ctx context.Context, input *RequestValidationInput, securityRequirement openapi3.SecurityRequirement) error { + names := make([]string, 0, len(securityRequirement)) + for name := range securityRequirement { + names = append(names, name) + } + sort.Strings(names) + + // Get authentication function + options := input.Options + if options == nil { + options = &Options{} + } + f := options.AuthenticationFunc + if f == nil { + return ErrAuthenticationServiceMissing + } + + var securitySchemes openapi3.SecuritySchemes + if components := input.Route.Spec.Components; components != nil { + securitySchemes = components.SecuritySchemes + } + + // For each scheme for the requirement + for _, name := range names { + var securityScheme *openapi3.SecurityScheme + if securitySchemes != nil { + if ref := securitySchemes[name]; ref != nil { + securityScheme = ref.Value + } + } + if securityScheme == nil { + return &RequestError{ + Input: input, + Err: fmt.Errorf("security scheme %q is not declared", name), + } + } + scopes := securityRequirement[name] + if err := f(ctx, &AuthenticationInput{ + RequestValidationInput: input, + SecuritySchemeName: name, + SecurityScheme: securityScheme, + Scopes: scopes, + }); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_request_input.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_request_input.go new file mode 100644 index 00000000..c7565ebb --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_request_input.go @@ -0,0 +1,38 @@ +package openapi3filter + +import ( + "net/http" + "net/url" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers" +) + +// A ContentParameterDecoder takes a parameter definition from the OpenAPI spec, +// and the value which we received for it. It is expected to return the +// value unmarshaled into an interface which can be traversed for +// validation, it should also return the schema to be used for validating the +// object, since there can be more than one in the content spec. +// +// If a query parameter appears multiple times, values[] will have more +// than one value, but for all other parameter types it should have just +// one. +type ContentParameterDecoder func(param *openapi3.Parameter, values []string) (any, *openapi3.Schema, error) + +type RequestValidationInput struct { + Request *http.Request + PathParams map[string]string + QueryParams url.Values + Route *routers.Route + Options *Options + ParamDecoder ContentParameterDecoder +} + +func (input *RequestValidationInput) GetQueryParams() url.Values { + q := input.QueryParams + if q == nil { + q = input.Request.URL.Query() + input.QueryParams = q + } + return q +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_response.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_response.go new file mode 100644 index 00000000..77f127e7 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_response.go @@ -0,0 +1,224 @@ +// Package openapi3filter validates that requests and inputs request an OpenAPI 3 specification file. +package openapi3filter + +import ( + "bytes" + "context" + "fmt" + "io" + "net/http" + "sort" + "strings" + + "github.com/getkin/kin-openapi/openapi3" +) + +// ValidateResponse is used to validate the given input according to previous +// loaded OpenAPIv3 spec. If the input does not match the OpenAPIv3 spec, a +// non-nil error will be returned. +// +// Note: One can tune the behavior of uniqueItems: true verification +// by registering a custom function with openapi3.RegisterArrayUniqueItemsChecker +func ValidateResponse(ctx context.Context, input *ResponseValidationInput) error { + req := input.RequestValidationInput.Request + switch req.Method { + case "HEAD": + return nil + } + status := input.Status + + // These status codes will never be validated. + // TODO: The list is probably missing some. + switch status { + case http.StatusNotModified, + http.StatusPermanentRedirect, + http.StatusTemporaryRedirect, + http.StatusMovedPermanently: + return nil + } + route := input.RequestValidationInput.Route + options := input.Options + if options == nil { + options = &Options{} + } + + // Find input for the current status + responses := route.Operation.Responses + if responses.Len() == 0 { + return nil + } + responseRef := responses.Status(status) // Response + if responseRef == nil { + responseRef = responses.Default() // Default input + } + if responseRef == nil { + // By default, status that is not documented is allowed. + if !options.IncludeResponseStatus { + return nil + } + return &ResponseError{Input: input, Reason: "status is not supported"} + } + response := responseRef.Value + if response == nil { + return &ResponseError{Input: input, Reason: "response has not been resolved"} + } + + opts := make([]openapi3.SchemaValidationOption, 0, 3) // 3 potential options here + if options.MultiError { + opts = append(opts, openapi3.MultiErrors()) + } + if options.customSchemaErrorFunc != nil { + opts = append(opts, openapi3.SetSchemaErrorMessageCustomizer(options.customSchemaErrorFunc)) + } + if options.ExcludeWriteOnlyValidations { + opts = append(opts, openapi3.DisableWriteOnlyValidation()) + } + + headers := make([]string, 0, len(response.Headers)) + for k := range response.Headers { + if k != headerCT { + headers = append(headers, k) + } + } + sort.Strings(headers) + for _, headerName := range headers { + headerRef := response.Headers[headerName] + if err := validateResponseHeader(headerName, headerRef, input, opts); err != nil { + return err + } + } + + if options.ExcludeResponseBody { + // A user turned off validation of a response's body. + return nil + } + + content := response.Content + if len(content) == 0 || options.ExcludeResponseBody { + // An operation does not contains a validation schema for responses with this status code. + return nil + } + + inputMIME := input.Header.Get(headerCT) + contentType := content.Get(inputMIME) + if contentType == nil { + return &ResponseError{ + Input: input, + Reason: fmt.Sprintf("response %s: %q", prefixInvalidCT, inputMIME), + } + } + + if contentType.Schema == nil { + // An operation does not contains a validation schema for responses with this status code. + return nil + } + + // Read response's body. + body := input.Body + + // Response would contain partial or empty input body + // after we begin reading. + // Ensure that this doesn't happen. + input.Body = nil + + // Ensure we close the reader + defer body.Close() + + // Read all + data, err := io.ReadAll(body) + if err != nil { + return &ResponseError{ + Input: input, + Reason: "failed to read response body", + Err: err, + } + } + + // Put the data back into the response. + input.SetBodyBytes(data) + + encFn := func(name string) *openapi3.Encoding { return contentType.Encoding[name] } + _, value, err := decodeBody(bytes.NewBuffer(data), input.Header, contentType.Schema, encFn) + if err != nil { + return &ResponseError{ + Input: input, + Reason: "failed to decode response body", + Err: err, + } + } + + // Validate data with the schema. + if err := contentType.Schema.Value.VisitJSON(value, append(opts, openapi3.VisitAsResponse())...); err != nil { + schemaId := getSchemaIdentifier(contentType.Schema) + schemaId = prependSpaceIfNeeded(schemaId) + return &ResponseError{ + Input: input, + Reason: fmt.Sprintf("response body doesn't match schema%s", schemaId), + Err: err, + } + } + return nil +} + +func validateResponseHeader(headerName string, headerRef *openapi3.HeaderRef, input *ResponseValidationInput, opts []openapi3.SchemaValidationOption) error { + var err error + var decodedValue any + var found bool + var sm *openapi3.SerializationMethod + dec := &headerParamDecoder{header: input.Header} + + if sm, err = headerRef.Value.SerializationMethod(); err != nil { + return &ResponseError{ + Input: input, + Reason: fmt.Sprintf("unable to get header %q serialization method", headerName), + Err: err, + } + } + + if decodedValue, found, err = decodeValue(dec, headerName, sm, headerRef.Value.Schema, headerRef.Value.Required); err != nil { + return &ResponseError{ + Input: input, + Reason: fmt.Sprintf("unable to decode header %q value", headerName), + Err: err, + } + } + + if found { + if err = headerRef.Value.Schema.Value.VisitJSON(decodedValue, opts...); err != nil { + return &ResponseError{ + Input: input, + Reason: fmt.Sprintf("response header %q doesn't match schema", headerName), + Err: err, + } + } + } else if headerRef.Value.Required { + return &ResponseError{ + Input: input, + Reason: fmt.Sprintf("response header %q missing", headerName), + } + } + return nil +} + +// getSchemaIdentifier gets something by which a schema could be identified. +// A schema by itself doesn't have a true identity field. This function makes +// a best effort to get a value that can fill that void. +func getSchemaIdentifier(schema *openapi3.SchemaRef) string { + var id string + + if schema != nil { + id = strings.TrimSpace(schema.Ref) + } + if id == "" && schema.Value != nil { + id = strings.TrimSpace(schema.Value.Title) + } + + return id +} + +func prependSpaceIfNeeded(value string) string { + if len(value) > 0 { + value = " " + value + } + return value +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_response_input.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_response_input.go new file mode 100644 index 00000000..5592fe61 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validate_response_input.go @@ -0,0 +1,41 @@ +package openapi3filter + +import ( + "bytes" + "io" + "net/http" +) + +type ResponseValidationInput struct { + RequestValidationInput *RequestValidationInput + Status int + Header http.Header + Body io.ReadCloser + Options *Options +} + +func (input *ResponseValidationInput) SetBodyBytes(value []byte) *ResponseValidationInput { + input.Body = io.NopCloser(bytes.NewReader(value)) + return input +} + +var JSONPrefixes = []string{ + ")]}',\n", +} + +// TrimJSONPrefix trims one of the possible prefixes +func TrimJSONPrefix(data []byte) []byte { +search: + for _, prefix := range JSONPrefixes { + if len(data) < len(prefix) { + continue + } + for i, b := range data[:len(prefix)] { + if b != prefix[i] { + continue search + } + } + return data[len(prefix):] + } + return data +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_error.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_error.go new file mode 100644 index 00000000..4153eef7 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_error.go @@ -0,0 +1,84 @@ +package openapi3filter + +import ( + "bytes" + "strconv" +) + +// ValidationError struct provides granular error information +// useful for communicating issues back to end user and developer. +// Based on https://jsonapi.org/format/#error-objects +type ValidationError struct { + // A unique identifier for this particular occurrence of the problem. + Id string `json:"id,omitempty" yaml:"id,omitempty"` + // The HTTP status code applicable to this problem. + Status int `json:"status,omitempty" yaml:"status,omitempty"` + // An application-specific error code, expressed as a string value. + Code string `json:"code,omitempty" yaml:"code,omitempty"` + // A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization. + Title string `json:"title,omitempty" yaml:"title,omitempty"` + // A human-readable explanation specific to this occurrence of the problem. + Detail string `json:"detail,omitempty" yaml:"detail,omitempty"` + // An object containing references to the source of the error + Source *ValidationErrorSource `json:"source,omitempty" yaml:"source,omitempty"` +} + +// ValidationErrorSource struct +type ValidationErrorSource struct { + // A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. \"/data\" for a primary data object, or \"/data/attributes/title\" for a specific attribute]. + Pointer string `json:"pointer,omitempty" yaml:"pointer,omitempty"` + // A string indicating which query parameter caused the error. + Parameter string `json:"parameter,omitempty" yaml:"parameter,omitempty"` +} + +var _ error = &ValidationError{} + +// Error implements the error interface. +func (e *ValidationError) Error() string { + b := bytes.NewBufferString("[") + if e.Status != 0 { + b.WriteString(strconv.Itoa(e.Status)) + } + b.WriteString("]") + b.WriteString("[") + if e.Code != "" { + b.WriteString(e.Code) + } + b.WriteString("]") + b.WriteString("[") + if e.Id != "" { + b.WriteString(e.Id) + } + b.WriteString("]") + b.WriteString(" ") + if e.Title != "" { + b.WriteString(e.Title) + b.WriteString(" ") + } + if e.Detail != "" { + b.WriteString("| ") + b.WriteString(e.Detail) + b.WriteString(" ") + } + if e.Source != nil { + b.WriteString("[source ") + if e.Source.Parameter != "" { + b.WriteString("parameter=") + b.WriteString(e.Source.Parameter) + } else if e.Source.Pointer != "" { + b.WriteString("pointer=") + b.WriteString(e.Source.Pointer) + } + b.WriteString("]") + } + + if b.Len() == 0 { + return "no error" + } + return b.String() +} + +// StatusCode implements the StatusCoder interface for DefaultErrorEncoder +func (e *ValidationError) StatusCode() int { + return e.Status +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_error_encoder.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_error_encoder.go new file mode 100644 index 00000000..c03fd139 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_error_encoder.go @@ -0,0 +1,186 @@ +package openapi3filter + +import ( + "context" + "fmt" + "net/http" + "strings" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers" +) + +// ValidationErrorEncoder wraps a base ErrorEncoder to handle ValidationErrors +type ValidationErrorEncoder struct { + Encoder ErrorEncoder +} + +// Encode implements the ErrorEncoder interface for encoding ValidationErrors +func (enc *ValidationErrorEncoder) Encode(ctx context.Context, err error, w http.ResponseWriter) { + enc.Encoder(ctx, ConvertErrors(err), w) +} + +// ConvertErrors converts all errors to the appropriate error format. +func ConvertErrors(err error) error { + if e, ok := err.(*routers.RouteError); ok { + return convertRouteError(e) + } + + e, ok := err.(*RequestError) + if !ok { + return err + } + + var cErr *ValidationError + if e.Err == nil { + cErr = convertBasicRequestError(e) + } else if e.Err == ErrInvalidRequired { + cErr = convertErrInvalidRequired(e) + } else if e.Err == ErrInvalidEmptyValue { + cErr = convertErrInvalidEmptyValue(e) + } else if innerErr, ok := e.Err.(*ParseError); ok { + cErr = convertParseError(e, innerErr) + } else if innerErr, ok := e.Err.(*openapi3.SchemaError); ok { + cErr = convertSchemaError(e, innerErr) + } + + if cErr != nil { + return cErr + } + return err +} + +func convertRouteError(e *routers.RouteError) *ValidationError { + status := http.StatusNotFound + if e.Error() == routers.ErrMethodNotAllowed.Error() { + status = http.StatusMethodNotAllowed + } + return &ValidationError{Status: status, Title: e.Error()} +} + +func convertBasicRequestError(e *RequestError) *ValidationError { + if strings.HasPrefix(e.Reason, prefixInvalidCT) { + if strings.HasSuffix(e.Reason, `""`) { + return &ValidationError{ + Status: http.StatusUnsupportedMediaType, + Title: "header Content-Type is required", + } + } + return &ValidationError{ + Status: http.StatusUnsupportedMediaType, + Title: prefixUnsupportedCT + strings.TrimPrefix(e.Reason, prefixInvalidCT), + } + } + return &ValidationError{ + Status: http.StatusBadRequest, + Title: e.Error(), + } +} + +func convertErrInvalidRequired(e *RequestError) *ValidationError { + if e.Err == ErrInvalidRequired && e.Parameter != nil { + return &ValidationError{ + Status: http.StatusBadRequest, + Title: fmt.Sprintf("parameter %q in %s is required", e.Parameter.Name, e.Parameter.In), + } + } + return &ValidationError{ + Status: http.StatusBadRequest, + Title: e.Error(), + } +} + +func convertErrInvalidEmptyValue(e *RequestError) *ValidationError { + if e.Err == ErrInvalidEmptyValue && e.Parameter != nil { + return &ValidationError{ + Status: http.StatusBadRequest, + Title: fmt.Sprintf("parameter %q in %s is not allowed to be empty", e.Parameter.Name, e.Parameter.In), + } + } + return &ValidationError{ + Status: http.StatusBadRequest, + Title: e.Error(), + } +} + +func convertParseError(e *RequestError, innerErr *ParseError) *ValidationError { + // We treat path params of the wrong type like a 404 instead of a 400 + if innerErr.Kind == KindInvalidFormat && e.Parameter != nil && e.Parameter.In == "path" { + return &ValidationError{ + Status: http.StatusNotFound, + Title: fmt.Sprintf("resource not found with %q value: %v", e.Parameter.Name, innerErr.Value), + } + } else if strings.HasPrefix(innerErr.Reason, prefixUnsupportedCT) { + return &ValidationError{ + Status: http.StatusUnsupportedMediaType, + Title: innerErr.Reason, + } + } else if innerErr.RootCause() != nil { + if rootErr, ok := innerErr.Cause.(*ParseError); ok && + rootErr.Kind == KindInvalidFormat && e.Parameter.In == "query" { + return &ValidationError{ + Status: http.StatusBadRequest, + Title: fmt.Sprintf("parameter %q in %s is invalid: %v is %s", + e.Parameter.Name, e.Parameter.In, rootErr.Value, rootErr.Reason), + } + } + return &ValidationError{ + Status: http.StatusBadRequest, + Title: innerErr.Reason, + } + } + return nil +} + +func convertSchemaError(e *RequestError, innerErr *openapi3.SchemaError) *ValidationError { + cErr := &ValidationError{Title: innerErr.Reason} + + // Handle "Origin" error + if originErr, ok := innerErr.Origin.(*openapi3.SchemaError); ok { + cErr = convertSchemaError(e, originErr) + } + + // Add http status code + if e.Parameter != nil { + cErr.Status = http.StatusBadRequest + } else if e.RequestBody != nil { + cErr.Status = http.StatusUnprocessableEntity + } + + // Add error source + if e.Parameter != nil { + // We have a JSONPointer in the query param too so need to + // make sure 'Parameter' check takes priority over 'Pointer' + cErr.Source = &ValidationErrorSource{Parameter: e.Parameter.Name} + } else if ptr := innerErr.JSONPointer(); ptr != nil { + cErr.Source = &ValidationErrorSource{Pointer: toJSONPointer(ptr)} + } + + // Add details on allowed values for enums + if innerErr.SchemaField == "enum" { + enums := make([]string, 0, len(innerErr.Schema.Enum)) + for _, enum := range innerErr.Schema.Enum { + enums = append(enums, fmt.Sprintf("%v", enum)) + } + cErr.Detail = fmt.Sprintf("value %v at %s must be one of: %s", + innerErr.Value, + toJSONPointer(innerErr.JSONPointer()), + strings.Join(enums, ", ")) + value := fmt.Sprintf("%v", innerErr.Value) + if e.Parameter != nil && + (e.Parameter.Explode == nil || *e.Parameter.Explode) && + (e.Parameter.Style == "" || e.Parameter.Style == "form") && + strings.Contains(value, ",") { + parts := strings.Split(value, ",") + cErr.Detail = fmt.Sprintf("%s; perhaps you intended '?%s=%s'", + cErr.Detail, + e.Parameter.Name, + strings.Join(parts, "&"+e.Parameter.Name+"=")) + } + } + return cErr +} + +func toJSONPointer(reversePath []string) string { + return "/" + strings.Join(reversePath, "/") +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_handler.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_handler.go new file mode 100644 index 00000000..d4bb1efa --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_handler.go @@ -0,0 +1,107 @@ +package openapi3filter + +import ( + "context" + "net/http" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers" + legacyrouter "github.com/getkin/kin-openapi/routers/legacy" +) + +// AuthenticationFunc allows for custom security requirement validation. +// A non-nil error fails authentication according to https://spec.openapis.org/oas/v3.1.0#security-requirement-object +// See ValidateSecurityRequirements +type AuthenticationFunc func(context.Context, *AuthenticationInput) error + +// NoopAuthenticationFunc is an AuthenticationFunc +func NoopAuthenticationFunc(context.Context, *AuthenticationInput) error { return nil } + +var _ AuthenticationFunc = NoopAuthenticationFunc + +type ValidationHandler struct { + Handler http.Handler + AuthenticationFunc AuthenticationFunc + File string + ErrorEncoder ErrorEncoder + router routers.Router +} + +func (h *ValidationHandler) Load() error { + loader := openapi3.NewLoader() + doc, err := loader.LoadFromFile(h.File) + if err != nil { + return err + } + if err := doc.Validate(loader.Context); err != nil { + return err + } + if h.router, err = legacyrouter.NewRouter(doc); err != nil { + return err + } + + // set defaults + if h.Handler == nil { + h.Handler = http.DefaultServeMux + } + if h.AuthenticationFunc == nil { + h.AuthenticationFunc = NoopAuthenticationFunc + } + if h.ErrorEncoder == nil { + h.ErrorEncoder = DefaultErrorEncoder + } + + return nil +} + +func (h *ValidationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if handled := h.before(w, r); handled { + return + } + // TODO: validateResponse + h.Handler.ServeHTTP(w, r) +} + +// Middleware implements gorilla/mux MiddlewareFunc +func (h *ValidationHandler) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if handled := h.before(w, r); handled { + return + } + // TODO: validateResponse + next.ServeHTTP(w, r) + }) +} + +func (h *ValidationHandler) before(w http.ResponseWriter, r *http.Request) (handled bool) { + if err := h.validateRequest(r); err != nil { + h.ErrorEncoder(r.Context(), err, w) + return true + } + return false +} + +func (h *ValidationHandler) validateRequest(r *http.Request) error { + // Find route + route, pathParams, err := h.router.FindRoute(r) + if err != nil { + return err + } + + options := &Options{ + AuthenticationFunc: h.AuthenticationFunc, + } + + // Validate request + requestValidationInput := &RequestValidationInput{ + Request: r, + PathParams: pathParams, + Route: route, + Options: options, + } + if err = ValidateRequest(r.Context(), requestValidationInput); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_kit.go b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_kit.go new file mode 100644 index 00000000..9e11e4fc --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/openapi3filter/validation_kit.go @@ -0,0 +1,85 @@ +package openapi3filter + +import ( + "context" + "encoding/json" + "net/http" +) + +/////////////////////////////////////////////////////////////////////////////////// +// We didn't want to tie kin-openapi too tightly with go-kit. +// This file contains the ErrorEncoder and DefaultErrorEncoder function +// borrowed from this project. +// +// 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. +/////////////////////////////////////////////////////////////////////////////////// + +// ErrorEncoder is responsible for encoding an error to the ResponseWriter. +// Users are encouraged to use custom ErrorEncoders to encode HTTP errors to +// their clients, and will likely want to pass and check for their own error +// types. See the example shipping/handling service. +type ErrorEncoder func(ctx context.Context, err error, w http.ResponseWriter) + +// StatusCoder is checked by DefaultErrorEncoder. If an error value implements +// StatusCoder, the StatusCode will be used when encoding the error. By default, +// StatusInternalServerError (500) is used. +type StatusCoder interface { + StatusCode() int +} + +// Headerer is checked by DefaultErrorEncoder. If an error value implements +// Headerer, the provided headers will be applied to the response writer, after +// the Content-Type is set. +type Headerer interface { + Headers() http.Header +} + +// DefaultErrorEncoder writes the error to the ResponseWriter, by default a +// content type of text/plain, a body of the plain text of the error, and a +// status code of 500. If the error implements Headerer, the provided headers +// will be applied to the response. If the error implements json.Marshaler, and +// the marshaling succeeds, a content type of application/json and the JSON +// encoded form of the error will be used. If the error implements StatusCoder, +// the provided StatusCode will be used instead of 500. +func DefaultErrorEncoder(_ context.Context, err error, w http.ResponseWriter) { + contentType, body := "text/plain; charset=utf-8", []byte(err.Error()) + if marshaler, ok := err.(json.Marshaler); ok { + if jsonBody, marshalErr := marshaler.MarshalJSON(); marshalErr == nil { + contentType, body = "application/json; charset=utf-8", jsonBody + } + } + w.Header().Set("Content-Type", contentType) + if headerer, ok := err.(Headerer); ok { + for k, values := range headerer.Headers() { + for _, v := range values { + w.Header().Add(k, v) + } + } + } + code := http.StatusInternalServerError + if sc, ok := err.(StatusCoder); ok { + code = sc.StatusCode() + } + w.WriteHeader(code) + w.Write(body) +} diff --git a/vendor/github.com/getkin/kin-openapi/routers/gorillamux/router.go b/vendor/github.com/getkin/kin-openapi/routers/gorillamux/router.go new file mode 100644 index 00000000..2d092426 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/routers/gorillamux/router.go @@ -0,0 +1,263 @@ +// Package gorillamux implements a router. +// +// It differs from the legacy router: +// * it provides somewhat granular errors: "path not found", "method not allowed". +// * it handles matching routes with extensions (e.g. /books/{id}.json) +// * it handles path patterns with a different syntax (e.g. /params/{x}/{y}/{z:.*}) +package gorillamux + +import ( + "net/http" + "net/url" + "regexp" + "sort" + "strings" + + "github.com/gorilla/mux" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers" +) + +var _ routers.Router = &Router{} + +// Router helps link http.Request.s and an OpenAPIv3 spec +type Router struct { + muxes []routeMux + routes []*routers.Route +} + +type varsf func(vars map[string]string) + +type routeMux struct { + muxRoute *mux.Route + varsUpdater varsf +} + +type srv struct { + schemes []string + host, base string + server *openapi3.Server + varsUpdater varsf +} + +var singleVariableMatcher = regexp.MustCompile(`^\{([^{}]+)\}$`) + +// TODO: Handle/HandlerFunc + ServeHTTP (When there is a match, the route variables can be retrieved calling mux.Vars(request)) + +// NewRouter creates a gorilla/mux router. +// Assumes spec is .Validate()d +// Note that a variable for the port number MUST have a default value and only this value will match as the port (see issue #367). +func NewRouter(doc *openapi3.T) (routers.Router, error) { + servers, err := makeServers(doc.Servers) + if err != nil { + return nil, err + } + + muxRouter := mux.NewRouter().UseEncodedPath() + r := &Router{} + for _, path := range doc.Paths.InMatchingOrder() { + pathItem := doc.Paths.Value(path) + if len(pathItem.Servers) > 0 { + if servers, err = makeServers(pathItem.Servers); err != nil { + return nil, err + } + } + + operations := pathItem.Operations() + methods := make([]string, 0, len(operations)) + for method := range operations { + methods = append(methods, method) + } + sort.Strings(methods) + + for _, s := range servers { + muxRoute := muxRouter.Path(s.base + path).Methods(methods...) + if schemes := s.schemes; len(schemes) != 0 { + muxRoute.Schemes(schemes...) + } + if host := s.host; host != "" { + muxRoute.Host(host) + } + if err := muxRoute.GetError(); err != nil { + return nil, err + } + r.muxes = append(r.muxes, routeMux{ + muxRoute: muxRoute, + varsUpdater: s.varsUpdater, + }) + r.routes = append(r.routes, &routers.Route{ + Spec: doc, + Server: s.server, + Path: path, + PathItem: pathItem, + Method: "", + Operation: nil, + }) + } + } + return r, nil +} + +// FindRoute extracts the route and parameters of an http.Request +func (r *Router) FindRoute(req *http.Request) (*routers.Route, map[string]string, error) { + for i, m := range r.muxes { + var match mux.RouteMatch + if m.muxRoute.Match(req, &match) { + if err := match.MatchErr; err != nil { + // What then? + } + vars := match.Vars + if f := m.varsUpdater; f != nil { + f(vars) + } + route := *r.routes[i] + route.Method = req.Method + route.Operation = route.Spec.Paths.Value(route.Path).GetOperation(route.Method) + return &route, vars, nil + } + switch match.MatchErr { + case nil: + case mux.ErrMethodMismatch: + return nil, nil, routers.ErrMethodNotAllowed + default: // What then? + } + } + return nil, nil, routers.ErrPathNotFound +} + +func makeServers(in openapi3.Servers) ([]srv, error) { + servers := make([]srv, 0, len(in)) + for _, server := range in { + serverURL := server.URL + if submatch := singleVariableMatcher.FindStringSubmatch(serverURL); submatch != nil { + sVar := submatch[1] + sVal := server.Variables[sVar].Default + serverURL = strings.ReplaceAll(serverURL, "{"+sVar+"}", sVal) + var varsUpdater varsf + if lhs := strings.TrimSuffix(serverURL, server.Variables[sVar].Default); lhs != "" { + varsUpdater = func(vars map[string]string) { vars[sVar] = lhs } + } + svr, err := newSrv(serverURL, server, varsUpdater) + if err != nil { + return nil, err + } + + servers = append(servers, svr) + continue + } + + // If a variable represents the port "http://domain.tld:{port}/bla" + // then url.Parse() cannot parse "http://domain.tld:`bEncode({port})`/bla" + // and mux is not able to set the {port} variable + // So we just use the default value for this variable. + // See https://github.com/getkin/kin-openapi/issues/367 + var varsUpdater varsf + if lhs := strings.Index(serverURL, ":{"); lhs > 0 { + rest := serverURL[lhs+len(":{"):] + rhs := strings.Index(rest, "}") + portVariable := rest[:rhs] + portValue := server.Variables[portVariable].Default + serverURL = strings.ReplaceAll(serverURL, "{"+portVariable+"}", portValue) + varsUpdater = func(vars map[string]string) { + vars[portVariable] = portValue + } + } + + svr, err := newSrv(serverURL, server, varsUpdater) + if err != nil { + return nil, err + } + servers = append(servers, svr) + } + if len(servers) == 0 { + servers = append(servers, srv{}) + } + + return servers, nil +} + +func newSrv(serverURL string, server *openapi3.Server, varsUpdater varsf) (srv, error) { + var schemes []string + if strings.Contains(serverURL, "://") { + scheme0 := strings.Split(serverURL, "://")[0] + schemes = permutePart(scheme0, server) + serverURL = strings.Replace(serverURL, scheme0+"://", schemes[0]+"://", 1) + } + + u, err := url.Parse(bEncode(serverURL)) + if err != nil { + return srv{}, err + } + path := bDecode(u.EscapedPath()) + if len(path) > 0 && path[len(path)-1] == '/' { + path = path[:len(path)-1] + } + svr := srv{ + host: bDecode(u.Host), //u.Hostname()? + base: path, + schemes: schemes, // scheme: []string{scheme0}, TODO: https://github.com/gorilla/mux/issues/624 + server: server, + varsUpdater: varsUpdater, + } + return svr, nil +} + +// Magic strings that temporarily replace "{}" so net/url.Parse() works +var blURL, brURL = strings.Repeat("-", 50), strings.Repeat("_", 50) + +func bEncode(s string) string { + s = strings.Replace(s, "{", blURL, -1) + s = strings.Replace(s, "}", brURL, -1) + return s +} +func bDecode(s string) string { + s = strings.Replace(s, blURL, "{", -1) + s = strings.Replace(s, brURL, "}", -1) + return s +} + +func permutePart(part0 string, srv *openapi3.Server) []string { + type mapAndSlice struct { + m map[string]struct{} + s []string + } + var2val := make(map[string]mapAndSlice) + max := 0 + for name0, v := range srv.Variables { + name := "{" + name0 + "}" + if !strings.Contains(part0, name) { + continue + } + m := map[string]struct{}{v.Default: {}} + for _, value := range v.Enum { + m[value] = struct{}{} + } + if l := len(m); l > max { + max = l + } + s := make([]string, 0, len(m)) + for value := range m { + s = append(s, value) + } + var2val[name] = mapAndSlice{m: m, s: s} + } + if len(var2val) == 0 { + return []string{part0} + } + + partsMap := make(map[string]struct{}, max*len(var2val)) + for i := 0; i < max; i++ { + part := part0 + for name, mas := range var2val { + part = strings.Replace(part, name, mas.s[i%len(mas.s)], -1) + } + partsMap[part] = struct{}{} + } + parts := make([]string, 0, len(partsMap)) + for part := range partsMap { + parts = append(parts, part) + } + sort.Strings(parts) + return parts +} diff --git a/vendor/github.com/getkin/kin-openapi/routers/legacy/pathpattern/node.go b/vendor/github.com/getkin/kin-openapi/routers/legacy/pathpattern/node.go new file mode 100644 index 00000000..75932a26 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/routers/legacy/pathpattern/node.go @@ -0,0 +1,328 @@ +// Package pathpattern implements path matching. +// +// Examples of supported patterns: +// - "/" +// - "/abc"" +// - "/abc/{variable}" (matches until next '/' or end-of-string) +// - "/abc/{variable*}" (matches everything, including "/abc" if "/abc" has root) +// - "/abc/{ variable | prefix_(.*}_suffix }" (matches regular expressions) +package pathpattern + +import ( + "bytes" + "fmt" + "regexp" + "sort" + "strings" +) + +var DefaultOptions = &Options{ + SupportWildcard: true, +} + +type Options struct { + SupportWildcard bool + SupportRegExp bool +} + +// PathFromHost converts a host pattern to a path pattern. +// +// Examples: +// - PathFromHost("some-subdomain.domain.com", false) -> "com/./domain/./some-subdomain" +// - PathFromHost("some-subdomain.domain.com", true) -> "com/./domain/./subdomain/-/some" +func PathFromHost(host string, specialDashes bool) string { + buf := make([]byte, 0, len(host)) + end := len(host) + + // Go from end to start + for start := end - 1; start >= 0; start-- { + switch host[start] { + case '.': + buf = append(buf, host[start+1:end]...) + buf = append(buf, '/', '.', '/') + end = start + case '-': + if specialDashes { + buf = append(buf, host[start+1:end]...) + buf = append(buf, '/', '-', '/') + end = start + } + } + } + buf = append(buf, host[:end]...) + return string(buf) +} + +type Node struct { + VariableNames []string + Value any + Suffixes SuffixList +} + +func (currentNode *Node) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 255)) + currentNode.toBuffer(buf, "") + return buf.String() +} + +func (currentNode *Node) toBuffer(buf *bytes.Buffer, linePrefix string) { + if value := currentNode.Value; value != nil { + buf.WriteString(linePrefix) + buf.WriteString("VALUE: ") + fmt.Fprint(buf, value) + buf.WriteString("\n") + } + suffixes := currentNode.Suffixes + if len(suffixes) > 0 { + newLinePrefix := linePrefix + " " + for _, suffix := range suffixes { + buf.WriteString(linePrefix) + buf.WriteString("PATTERN: ") + buf.WriteString(suffix.String()) + buf.WriteString("\n") + suffix.Node.toBuffer(buf, newLinePrefix) + } + } +} + +type SuffixKind int + +// Note that order is important! +const ( + // SuffixKindConstant matches a constant string + SuffixKindConstant = SuffixKind(iota) + + // SuffixKindRegExp matches a regular expression + SuffixKindRegExp + + // SuffixKindVariable matches everything until '/' + SuffixKindVariable + + // SuffixKindEverything matches everything (until end-of-string) + SuffixKindEverything +) + +// Suffix describes condition that +type Suffix struct { + Kind SuffixKind + Pattern string + + // compiled regular expression + regExp *regexp.Regexp + + // Next node + Node *Node +} + +func EqualSuffix(a, b Suffix) bool { + return a.Kind == b.Kind && a.Pattern == b.Pattern +} + +func (suffix Suffix) String() string { + switch suffix.Kind { + case SuffixKindConstant: + return suffix.Pattern + case SuffixKindVariable: + return "{_}" + case SuffixKindEverything: + return "{_*}" + default: + return "{_|" + suffix.Pattern + "}" + } +} + +type SuffixList []Suffix + +func (list SuffixList) Less(i, j int) bool { + a, b := list[i], list[j] + ak, bk := a.Kind, b.Kind + if ak < bk { + return true + } else if bk < ak { + return false + } + return a.Pattern > b.Pattern +} + +func (list SuffixList) Len() int { + return len(list) +} + +func (list SuffixList) Swap(i, j int) { + a, b := list[i], list[j] + list[i], list[j] = b, a +} + +func (currentNode *Node) MustAdd(path string, value any, options *Options) { + node, err := currentNode.CreateNode(path, options) + if err != nil { + panic(err) + } + node.Value = value +} + +func (currentNode *Node) Add(path string, value any, options *Options) error { + node, err := currentNode.CreateNode(path, options) + if err != nil { + return err + } + node.Value = value + return nil +} + +func (currentNode *Node) CreateNode(path string, options *Options) (*Node, error) { + if options == nil { + options = DefaultOptions + } + for strings.HasSuffix(path, "/") { + path = path[:len(path)-1] + } + remaining := path + var variableNames []string +loop: + for { + //remaining = strings.TrimPrefix(remaining, "/") + if len(remaining) == 0 { + // This node is the right one + // Check whether another route already leads to this node + currentNode.VariableNames = variableNames + return currentNode, nil + } + + suffix := Suffix{} + var i int + if strings.HasPrefix(remaining, "/") { + remaining = remaining[1:] + suffix.Kind = SuffixKindConstant + suffix.Pattern = "/" + } else { + i = strings.IndexAny(remaining, "/{") + if i < 0 { + i = len(remaining) + } + if i > 0 { + // Constant string pattern + suffix.Kind = SuffixKindConstant + suffix.Pattern = remaining[:i] + remaining = remaining[i:] + } else if remaining[0] == '{' { + // This is probably a variable + suffix.Kind = SuffixKindVariable + + // Find variable name + i := strings.IndexByte(remaining, '}') + if i < 0 { + return nil, fmt.Errorf("missing '}' in: %s", path) + } + variableName := strings.TrimSpace(remaining[1:i]) + remaining = remaining[i+1:] + + if options.SupportRegExp { + // See if it has regular expression + i = strings.IndexByte(variableName, '|') + if i >= 0 { + suffix.Kind = SuffixKindRegExp + suffix.Pattern = strings.TrimSpace(variableName[i+1:]) + variableName = strings.TrimSpace(variableName[:i]) + } + } + if suffix.Kind == SuffixKindVariable && options.SupportWildcard { + if strings.HasSuffix(variableName, "*") { + suffix.Kind = SuffixKindEverything + } + } + variableNames = append(variableNames, variableName) + } + } + + // Find existing matcher + for _, existing := range currentNode.Suffixes { + if EqualSuffix(existing, suffix) { + currentNode = existing.Node + continue loop + } + } + + // Compile regular expression + if suffix.Kind == SuffixKindRegExp { + regExp, err := regexp.Compile(suffix.Pattern) + if err != nil { + return nil, fmt.Errorf("invalid regular expression in: %s", path) + } + suffix.regExp = regExp + } + + // Create new node + newNode := &Node{} + suffix.Node = newNode + currentNode.Suffixes = append(currentNode.Suffixes, suffix) + sort.Sort(currentNode.Suffixes) + currentNode = newNode + continue loop + } +} + +func (currentNode *Node) Match(path string) (*Node, []string) { + for strings.HasSuffix(path, "/") { + path = path[:len(path)-1] + } + variableValues := make([]string, 0, 8) + return currentNode.matchRemaining(path, variableValues) +} + +func (currentNode *Node) matchRemaining(remaining string, paramValues []string) (*Node, []string) { + // Check if this node matches + if len(remaining) == 0 && currentNode.Value != nil { + return currentNode, paramValues + } + + // See if any suffix matches + for _, suffix := range currentNode.Suffixes { + var resultNode *Node + var resultValues []string + switch suffix.Kind { + case SuffixKindConstant: + pattern := suffix.Pattern + if strings.HasPrefix(remaining, pattern) { + newRemaining := remaining[len(pattern):] + resultNode, resultValues = suffix.Node.matchRemaining(newRemaining, paramValues) + } else if len(remaining) == 0 && pattern == "/" { + resultNode, resultValues = suffix.Node.matchRemaining(remaining, paramValues) + } + case SuffixKindVariable: + i := strings.IndexByte(remaining, '/') + if i < 0 { + i = len(remaining) + } + newParamValues := append(paramValues, remaining[:i]) + newRemaining := remaining[i:] + resultNode, resultValues = suffix.Node.matchRemaining(newRemaining, newParamValues) + case SuffixKindEverything: + newParamValues := append(paramValues, remaining) + resultNode, resultValues = suffix.Node, newParamValues + case SuffixKindRegExp: + i := strings.IndexByte(remaining, '/') + if i < 0 { + i = len(remaining) + } + paramValue := remaining[:i] + regExp := suffix.regExp + if regExp.MatchString(paramValue) { + matches := regExp.FindStringSubmatch(paramValue) + if len(matches) > 1 { + paramValue = matches[1] + } + newParamValues := append(paramValues, paramValue) + newRemaining := remaining[i:] + resultNode, resultValues = suffix.Node.matchRemaining(newRemaining, newParamValues) + } + } + if resultNode != nil && resultNode.Value != nil { + // This suffix matched + return resultNode, resultValues + } + } + + // No suffix matched + return nil, nil +} diff --git a/vendor/github.com/getkin/kin-openapi/routers/legacy/router.go b/vendor/github.com/getkin/kin-openapi/routers/legacy/router.go new file mode 100644 index 00000000..306449d3 --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/routers/legacy/router.go @@ -0,0 +1,164 @@ +// Package legacy implements a router. +// +// It differs from the gorilla/mux router: +// * it provides granular errors: "path not found", "method not allowed", "variable missing from path" +// * it does not handle matching routes with extensions (e.g. /books/{id}.json) +// * it handles path patterns with a different syntax (e.g. /params/{x}/{y}/{z.*}) +package legacy + +import ( + "context" + "errors" + "fmt" + "net/http" + "strings" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers" + "github.com/getkin/kin-openapi/routers/legacy/pathpattern" +) + +// Routers maps a HTTP request to a Router. +type Routers []*Router + +// FindRoute extracts the route and parameters of an http.Request +func (rs Routers) FindRoute(req *http.Request) (routers.Router, *routers.Route, map[string]string, error) { + for _, router := range rs { + // Skip routers that have DO NOT have servers + if len(router.doc.Servers) == 0 { + continue + } + route, pathParams, err := router.FindRoute(req) + if err == nil { + return router, route, pathParams, nil + } + } + for _, router := range rs { + // Skip routers that DO have servers + if len(router.doc.Servers) > 0 { + continue + } + route, pathParams, err := router.FindRoute(req) + if err == nil { + return router, route, pathParams, nil + } + } + return nil, nil, nil, &routers.RouteError{ + Reason: "none of the routers match", + } +} + +// Router maps a HTTP request to an OpenAPI operation. +type Router struct { + doc *openapi3.T + pathNode *pathpattern.Node +} + +// NewRouter creates a new router. +// +// If the given OpenAPIv3 document has servers, router will use them. +// All operations of the document will be added to the router. +func NewRouter(doc *openapi3.T, opts ...openapi3.ValidationOption) (routers.Router, error) { + if err := doc.Validate(context.Background(), opts...); err != nil { + return nil, fmt.Errorf("validating OpenAPI failed: %w", err) + } + router := &Router{doc: doc} + root := router.node() + for path, pathItem := range doc.Paths.Map() { + for method, operation := range pathItem.Operations() { + method = strings.ToUpper(method) + if err := root.Add(method+" "+path, &routers.Route{ + Spec: doc, + Path: path, + PathItem: pathItem, + Method: method, + Operation: operation, + }, nil); err != nil { + return nil, err + } + } + } + return router, nil +} + +// AddRoute adds a route in the router. +func (router *Router) AddRoute(route *routers.Route) error { + method := route.Method + if method == "" { + return errors.New("route is missing method") + } + method = strings.ToUpper(method) + path := route.Path + if path == "" { + return errors.New("route is missing path") + } + return router.node().Add(method+" "+path, router, nil) +} + +func (router *Router) node() *pathpattern.Node { + root := router.pathNode + if root == nil { + root = &pathpattern.Node{} + router.pathNode = root + } + return root +} + +// FindRoute extracts the route and parameters of an http.Request +func (router *Router) FindRoute(req *http.Request) (*routers.Route, map[string]string, error) { + method, url := req.Method, req.URL + doc := router.doc + + // Get server + servers := doc.Servers + var server *openapi3.Server + var remainingPath string + var pathParams map[string]string + if len(servers) == 0 { + remainingPath = url.Path + } else { + var paramValues []string + server, paramValues, remainingPath = servers.MatchURL(url) + if server == nil { + return nil, nil, &routers.RouteError{ + Reason: routers.ErrPathNotFound.Error(), + } + } + pathParams = make(map[string]string) + paramNames, err := server.ParameterNames() + if err != nil { + return nil, nil, err + } + for i, value := range paramValues { + name := paramNames[i] + pathParams[name] = value + } + } + + // Get PathItem + root := router.node() + var route *routers.Route + node, paramValues := root.Match(method + " " + remainingPath) + if node != nil { + route, _ = node.Value.(*routers.Route) + } + if route == nil { + pathItem := doc.Paths.Value(remainingPath) + if pathItem == nil { + return nil, nil, &routers.RouteError{Reason: routers.ErrPathNotFound.Error()} + } + if pathItem.GetOperation(method) == nil { + return nil, nil, &routers.RouteError{Reason: routers.ErrMethodNotAllowed.Error()} + } + } + + if pathParams == nil { + pathParams = make(map[string]string, len(paramValues)) + } + paramKeys := node.VariableNames + for i, value := range paramValues { + key := strings.TrimSuffix(paramKeys[i], "*") + pathParams[key] = value + } + return route, pathParams, nil +} diff --git a/vendor/github.com/getkin/kin-openapi/routers/types.go b/vendor/github.com/getkin/kin-openapi/routers/types.go new file mode 100644 index 00000000..93746cfe --- /dev/null +++ b/vendor/github.com/getkin/kin-openapi/routers/types.go @@ -0,0 +1,42 @@ +package routers + +import ( + "net/http" + + "github.com/getkin/kin-openapi/openapi3" +) + +// Router helps link http.Request.s and an OpenAPIv3 spec +type Router interface { + // FindRoute matches an HTTP request with the operation it resolves to. + // Hosts are matched from the OpenAPIv3 servers key. + // + // If you experience ErrPathNotFound and have localhost hosts specified as your servers, + // turning these server URLs as relative (leaving only the path) should resolve this. + // + // See openapi3filter for example uses with request and response validation. + FindRoute(req *http.Request) (route *Route, pathParams map[string]string, err error) +} + +// Route describes the operation an http.Request can match +type Route struct { + Spec *openapi3.T + Server *openapi3.Server + Path string + PathItem *openapi3.PathItem + Method string + Operation *openapi3.Operation +} + +// ErrPathNotFound is returned when no route match is found +var ErrPathNotFound error = &RouteError{"no matching operation was found"} + +// ErrMethodNotAllowed is returned when no method of the matched route matches +var ErrMethodNotAllowed error = &RouteError{"method not allowed"} + +// RouteError describes Router errors +type RouteError struct { + Reason string +} + +func (e *RouteError) Error() string { return e.Reason } diff --git a/vendor/github.com/gorilla/mux/.editorconfig b/vendor/github.com/gorilla/mux/.editorconfig new file mode 100644 index 00000000..c6b74c3e --- /dev/null +++ b/vendor/github.com/gorilla/mux/.editorconfig @@ -0,0 +1,20 @@ +; https://editorconfig.org/ + +root = true + +[*] +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[{Makefile,go.mod,go.sum,*.go,.gitmodules}] +indent_style = tab +indent_size = 4 + +[*.md] +indent_size = 4 +trim_trailing_whitespace = false + +eclint_indent_style = unset \ No newline at end of file diff --git a/vendor/github.com/gorilla/mux/.gitignore b/vendor/github.com/gorilla/mux/.gitignore new file mode 100644 index 00000000..84039fec --- /dev/null +++ b/vendor/github.com/gorilla/mux/.gitignore @@ -0,0 +1 @@ +coverage.coverprofile diff --git a/vendor/github.com/gorilla/mux/LICENSE b/vendor/github.com/gorilla/mux/LICENSE new file mode 100644 index 00000000..bb9d80bc --- /dev/null +++ b/vendor/github.com/gorilla/mux/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2023 The Gorilla Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gorilla/mux/Makefile b/vendor/github.com/gorilla/mux/Makefile new file mode 100644 index 00000000..98f5ab75 --- /dev/null +++ b/vendor/github.com/gorilla/mux/Makefile @@ -0,0 +1,34 @@ +GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '') +GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +GO_SEC=$(shell which gosec 2> /dev/null || echo '') +GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest + +GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '') +GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest + +.PHONY: golangci-lint +golangci-lint: + $(if $(GO_LINT), ,go install $(GO_LINT_URI)) + @echo "##### Running golangci-lint" + golangci-lint run -v + +.PHONY: gosec +gosec: + $(if $(GO_SEC), ,go install $(GO_SEC_URI)) + @echo "##### Running gosec" + gosec ./... + +.PHONY: govulncheck +govulncheck: + $(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI)) + @echo "##### Running govulncheck" + govulncheck ./... + +.PHONY: verify +verify: golangci-lint gosec govulncheck + +.PHONY: test +test: + @echo "##### Running tests" + go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./... \ No newline at end of file diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md new file mode 100644 index 00000000..382513d5 --- /dev/null +++ b/vendor/github.com/gorilla/mux/README.md @@ -0,0 +1,812 @@ +# gorilla/mux + +![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg) +[![codecov](https://codecov.io/github/gorilla/mux/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/mux) +[![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) +[![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) + + +![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5) + +Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to +their respective handler. + +The name mux stands for "HTTP request multiplexer". Like the standard `http.ServeMux`, `mux.Router` matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are: + +* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`. +* Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers. +* URL hosts, paths and query values can have variables with an optional regular expression. +* Registered URLs can be built, or "reversed", which helps maintaining references to resources. +* Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching. + +--- + +* [Install](#install) +* [Examples](#examples) +* [Matching Routes](#matching-routes) +* [Static Files](#static-files) +* [Serving Single Page Applications](#serving-single-page-applications) (e.g. React, Vue, Ember.js, etc.) +* [Registered URLs](#registered-urls) +* [Walking Routes](#walking-routes) +* [Graceful Shutdown](#graceful-shutdown) +* [Middleware](#middleware) +* [Handling CORS Requests](#handling-cors-requests) +* [Testing Handlers](#testing-handlers) +* [Full Example](#full-example) + +--- + +## Install + +With a [correctly configured](https://golang.org/doc/install#testing) Go toolchain: + +```sh +go get -u github.com/gorilla/mux +``` + +## Examples + +Let's start registering a couple of URL paths and handlers: + +```go +func main() { + r := mux.NewRouter() + r.HandleFunc("/", HomeHandler) + r.HandleFunc("/products", ProductsHandler) + r.HandleFunc("/articles", ArticlesHandler) + http.Handle("/", r) +} +``` + +Here we register three routes mapping URL paths to handlers. This is equivalent to how `http.HandleFunc()` works: if an incoming request URL matches one of the paths, the corresponding handler is called passing (`http.ResponseWriter`, `*http.Request`) as parameters. + +Paths can have variables. They are defined using the format `{name}` or `{name:pattern}`. If a regular expression pattern is not defined, the matched variable will be anything until the next slash. For example: + +```go +r := mux.NewRouter() +r.HandleFunc("/products/{key}", ProductHandler) +r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) +r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) +``` + +The names are used to create a map of route variables which can be retrieved calling `mux.Vars()`: + +```go +func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Category: %v\n", vars["category"]) +} +``` + +And this is all you need to know about the basic usage. More advanced options are explained below. + +### Matching Routes + +Routes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables: + +```go +r := mux.NewRouter() +// Only matches if domain is "www.example.com". +r.Host("www.example.com") +// Matches a dynamic subdomain. +r.Host("{subdomain:[a-z]+}.example.com") +``` + +There are several other matchers that can be added. To match path prefixes: + +```go +r.PathPrefix("/products/") +``` + +...or HTTP methods: + +```go +r.Methods("GET", "POST") +``` + +...or URL schemes: + +```go +r.Schemes("https") +``` + +...or header values: + +```go +r.Headers("X-Requested-With", "XMLHttpRequest") +``` + +...or query values: + +```go +r.Queries("key", "value") +``` + +...or to use a custom matcher function: + +```go +r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { + return r.ProtoMajor == 0 +}) +``` + +...and finally, it is possible to combine several matchers in a single route: + +```go +r.HandleFunc("/products", ProductsHandler). + Host("www.example.com"). + Methods("GET"). + Schemes("http") +``` + +Routes are tested in the order they were added to the router. If two routes match, the first one wins: + +```go +r := mux.NewRouter() +r.HandleFunc("/specific", specificHandler) +r.PathPrefix("/").Handler(catchAllHandler) +``` + +Setting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it "subrouting". + +For example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a "subrouter" from it: + +```go +r := mux.NewRouter() +s := r.Host("www.example.com").Subrouter() +``` + +Then register routes in the subrouter: + +```go +s.HandleFunc("/products/", ProductsHandler) +s.HandleFunc("/products/{key}", ProductHandler) +s.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) +``` + +The three URL paths we registered above will only be tested if the domain is `www.example.com`, because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route. + +Subrouters can be used to create domain or path "namespaces": you define subrouters in a central place and then parts of the app can register its paths relatively to a given subrouter. + +There's one more thing about subroutes. When a subrouter has a path prefix, the inner routes use it as base for their paths: + +```go +r := mux.NewRouter() +s := r.PathPrefix("/products").Subrouter() +// "/products/" +s.HandleFunc("/", ProductsHandler) +// "/products/{key}/" +s.HandleFunc("/{key}/", ProductHandler) +// "/products/{key}/details" +s.HandleFunc("/{key}/details", ProductDetailsHandler) +``` + + +### Static Files + +Note that the path provided to `PathPrefix()` represents a "wildcard": calling +`PathPrefix("/static/").Handler(...)` means that the handler will be passed any +request that matches "/static/\*". This makes it easy to serve static files with mux: + +```go +func main() { + var dir string + + flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") + flag.Parse() + r := mux.NewRouter() + + // This will serve files under http://localhost:8000/static/ + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) + + srv := &http.Server{ + Handler: r, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + +### Serving Single Page Applications + +Most of the time it makes sense to serve your SPA on a separate web server from your API, +but sometimes it's desirable to serve them both from one place. It's possible to write a simple +handler for serving your SPA (for use with React Router's [BrowserRouter](https://reacttraining.com/react-router/web/api/BrowserRouter) for example), and leverage +mux's powerful routing for your API endpoints. + +```go +package main + +import ( + "encoding/json" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gorilla/mux" +) + +// spaHandler implements the http.Handler interface, so we can use it +// to respond to HTTP requests. The path to the static directory and +// path to the index file within that static directory are used to +// serve the SPA in the given static directory. +type spaHandler struct { + staticPath string + indexPath string +} + +// ServeHTTP inspects the URL path to locate a file within the static dir +// on the SPA handler. If a file is found, it will be served. If not, the +// file located at the index path on the SPA handler will be served. This +// is suitable behavior for serving an SPA (single page application). +func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Join internally call path.Clean to prevent directory traversal + path := filepath.Join(h.staticPath, r.URL.Path) + + // check whether a file exists or is a directory at the given path + fi, err := os.Stat(path) + if os.IsNotExist(err) || fi.IsDir() { + // file does not exist or path is a directory, serve index.html + http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath)) + return + } + + if err != nil { + // if we got an error (that wasn't that the file doesn't exist) stating the + // file, return a 500 internal server error and stop + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // otherwise, use http.FileServer to serve the static file + http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r) +} + +func main() { + router := mux.NewRouter() + + router.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { + // an example API handler + json.NewEncoder(w).Encode(map[string]bool{"ok": true}) + }) + + spa := spaHandler{staticPath: "build", indexPath: "index.html"} + router.PathPrefix("/").Handler(spa) + + srv := &http.Server{ + Handler: router, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + +### Registered URLs + +Now let's see how to build registered URLs. + +Routes can be named. All routes that define a name can have their URLs built, or "reversed". We define a name calling `Name()` on a route. For example: + +```go +r := mux.NewRouter() +r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). + Name("article") +``` + +To build a URL, get the route and call the `URL()` method, passing a sequence of key/value pairs for the route variables. For the previous route, we would do: + +```go +url, err := r.Get("article").URL("category", "technology", "id", "42") +``` + +...and the result will be a `url.URL` with the following path: + +``` +"/articles/technology/42" +``` + +This also works for host and query value variables: + +```go +r := mux.NewRouter() +r.Host("{subdomain}.example.com"). + Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). + HandlerFunc(ArticleHandler). + Name("article") + +// url.String() will be "http://news.example.com/articles/technology/42?filter=gorilla" +url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42", + "filter", "gorilla") +``` + +All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match. + +Regex support also exists for matching Headers within a route. For example, we could do: + +```go +r.HeadersRegexp("Content-Type", "application/(text|json)") +``` + +...and the route will match both requests with a Content-Type of `application/json` as well as `application/text` + +There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do: + +```go +// "http://news.example.com/" +host, err := r.Get("article").URLHost("subdomain", "news") + +// "/articles/technology/42" +path, err := r.Get("article").URLPath("category", "technology", "id", "42") +``` + +And if you use subrouters, host and path defined separately can be built as well: + +```go +r := mux.NewRouter() +s := r.Host("{subdomain}.example.com").Subrouter() +s.Path("/articles/{category}/{id:[0-9]+}"). + HandlerFunc(ArticleHandler). + Name("article") + +// "http://news.example.com/articles/technology/42" +url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42") +``` + +To find all the required variables for a given route when calling `URL()`, the method `GetVarNames()` is available: +```go +r := mux.NewRouter() +r.Host("{domain}"). + Path("/{group}/{item_id}"). + Queries("some_data1", "{some_data1}"). + Queries("some_data2", "{some_data2}"). + Name("article") + +// Will print [domain group item_id some_data1 some_data2] +fmt.Println(r.Get("article").GetVarNames()) + +``` +### Walking Routes + +The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example, +the following prints all of the registered routes: + +```go +package main + +import ( + "fmt" + "net/http" + "strings" + + "github.com/gorilla/mux" +) + +func handler(w http.ResponseWriter, r *http.Request) { + return +} + +func main() { + r := mux.NewRouter() + r.HandleFunc("/", handler) + r.HandleFunc("/products", handler).Methods("POST") + r.HandleFunc("/articles", handler).Methods("GET") + r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") + r.HandleFunc("/authors", handler).Queries("surname", "{surname}") + err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { + pathTemplate, err := route.GetPathTemplate() + if err == nil { + fmt.Println("ROUTE:", pathTemplate) + } + pathRegexp, err := route.GetPathRegexp() + if err == nil { + fmt.Println("Path regexp:", pathRegexp) + } + queriesTemplates, err := route.GetQueriesTemplates() + if err == nil { + fmt.Println("Queries templates:", strings.Join(queriesTemplates, ",")) + } + queriesRegexps, err := route.GetQueriesRegexp() + if err == nil { + fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ",")) + } + methods, err := route.GetMethods() + if err == nil { + fmt.Println("Methods:", strings.Join(methods, ",")) + } + fmt.Println() + return nil + }) + + if err != nil { + fmt.Println(err) + } + + http.Handle("/", r) +} +``` + +### Graceful Shutdown + +Go 1.8 introduced the ability to [gracefully shutdown](https://golang.org/doc/go1.8#http_shutdown) a `*http.Server`. Here's how to do that alongside `mux`: + +```go +package main + +import ( + "context" + "flag" + "log" + "net/http" + "os" + "os/signal" + "time" + + "github.com/gorilla/mux" +) + +func main() { + var wait time.Duration + flag.DurationVar(&wait, "graceful-timeout", time.Second * 15, "the duration for which the server gracefully wait for existing connections to finish - e.g. 15s or 1m") + flag.Parse() + + r := mux.NewRouter() + // Add your routes as needed + + srv := &http.Server{ + Addr: "0.0.0.0:8080", + // Good practice to set timeouts to avoid Slowloris attacks. + WriteTimeout: time.Second * 15, + ReadTimeout: time.Second * 15, + IdleTimeout: time.Second * 60, + Handler: r, // Pass our instance of gorilla/mux in. + } + + // Run our server in a goroutine so that it doesn't block. + go func() { + if err := srv.ListenAndServe(); err != nil { + log.Println(err) + } + }() + + c := make(chan os.Signal, 1) + // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C) + // SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught. + signal.Notify(c, os.Interrupt) + + // Block until we receive our signal. + <-c + + // Create a deadline to wait for. + ctx, cancel := context.WithTimeout(context.Background(), wait) + defer cancel() + // Doesn't block if no connections, but will otherwise wait + // until the timeout deadline. + srv.Shutdown(ctx) + // Optionally, you could run srv.Shutdown in a goroutine and block on + // <-ctx.Done() if your application should wait for other services + // to finalize based on context cancellation. + log.Println("shutting down") + os.Exit(0) +} +``` + +### Middleware + +Mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed in the order they are added if a match is found, including its subrouters. +Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or `ResponseWriter` hijacking. + +Mux middlewares are defined using the de facto standard type: + +```go +type MiddlewareFunc func(http.Handler) http.Handler +``` + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc. This takes advantage of closures being able access variables from the context where they are created, while retaining the signature enforced by the receivers. + +A very basic middleware which logs the URI of the request being handled could be written as: + +```go +func loggingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) +} +``` + +Middlewares can be added to a router using `Router.Use()`: + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) +r.Use(loggingMiddleware) +``` + +A more complex authentication middleware, which maps session token to users, could be written as: + +```go +// Define our struct +type authenticationMiddleware struct { + tokenUsers map[string]string +} + +// Initialize it somewhere +func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" +} + +// Middleware function, which will be called for each request +func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + // Pass down the request to the next middleware (or final handler) + next.ServeHTTP(w, r) + } else { + // Write an error and stop the handler chain + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) +} +``` + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) + +amw := authenticationMiddleware{tokenUsers: make(map[string]string)} +amw.Populate() + +r.Use(amw.Middleware) +``` + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it. + +### Handling CORS Requests + +[CORSMethodMiddleware](https://godoc.org/github.com/gorilla/mux#CORSMethodMiddleware) intends to make it easier to strictly set the `Access-Control-Allow-Methods` response header. + +* You will still need to use your own CORS handler to set the other CORS headers such as `Access-Control-Allow-Origin` +* The middleware will set the `Access-Control-Allow-Methods` header to all the method matchers (e.g. `r.Methods(http.MethodGet, http.MethodPut, http.MethodOptions)` -> `Access-Control-Allow-Methods: GET,PUT,OPTIONS`) on a route +* If you do not specify any methods, then: +> _Important_: there must be an `OPTIONS` method matcher for the middleware to set the headers. + +Here is an example of using `CORSMethodMiddleware` along with a custom `OPTIONS` handler to set all the required CORS headers: + +```go +package main + +import ( + "net/http" + "github.com/gorilla/mux" +) + +func main() { + r := mux.NewRouter() + + // IMPORTANT: you must specify an OPTIONS method matcher for the middleware to set CORS headers + r.HandleFunc("/foo", fooHandler).Methods(http.MethodGet, http.MethodPut, http.MethodPatch, http.MethodOptions) + r.Use(mux.CORSMethodMiddleware(r)) + + http.ListenAndServe(":8080", r) +} + +func fooHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + if r.Method == http.MethodOptions { + return + } + + w.Write([]byte("foo")) +} +``` + +And an request to `/foo` using something like: + +```bash +curl localhost:8080/foo -v +``` + +Would look like: + +```bash +* Trying ::1... +* TCP_NODELAY set +* Connected to localhost (::1) port 8080 (#0) +> GET /foo HTTP/1.1 +> Host: localhost:8080 +> User-Agent: curl/7.59.0 +> Accept: */* +> +< HTTP/1.1 200 OK +< Access-Control-Allow-Methods: GET,PUT,PATCH,OPTIONS +< Access-Control-Allow-Origin: * +< Date: Fri, 28 Jun 2019 20:13:30 GMT +< Content-Length: 3 +< Content-Type: text/plain; charset=utf-8 +< +* Connection #0 to host localhost left intact +foo +``` + +### Testing Handlers + +Testing handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_. + +First, our simple HTTP handler: + +```go +// endpoints.go +package main + +func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { + // A very simple health check. + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + // In the future we could report back on the status of our DB, or our cache + // (e.g. Redis) by performing a simple PING, and include them in the response. + io.WriteString(w, `{"alive": true}`) +} + +func main() { + r := mux.NewRouter() + r.HandleFunc("/health", HealthCheckHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test code: + +```go +// endpoints_test.go +package main + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestHealthCheckHandler(t *testing.T) { + // Create a request to pass to our handler. We don't have any query parameters for now, so we'll + // pass 'nil' as the third parameter. + req, err := http.NewRequest("GET", "/health", nil) + if err != nil { + t.Fatal(err) + } + + // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. + rr := httptest.NewRecorder() + handler := http.HandlerFunc(HealthCheckHandler) + + // Our handlers satisfy http.Handler, so we can call their ServeHTTP method + // directly and pass in our Request and ResponseRecorder. + handler.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusOK) + } + + // Check the response body is what we expect. + expected := `{"alive": true}` + if rr.Body.String() != expected { + t.Errorf("handler returned unexpected body: got %v want %v", + rr.Body.String(), expected) + } +} +``` + +In the case that our routes have [variables](#examples), we can pass those in the request. We could write +[table-driven tests](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go) to test multiple +possible route variables as needed. + +```go +// endpoints.go +func main() { + r := mux.NewRouter() + // A route with a route variable: + r.HandleFunc("/metrics/{type}", MetricsHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test file, with a table-driven test of `routeVariables`: + +```go +// endpoints_test.go +func TestMetricsHandler(t *testing.T) { + tt := []struct{ + routeVariable string + shouldPass bool + }{ + {"goroutines", true}, + {"heap", true}, + {"counters", true}, + {"queries", true}, + {"adhadaeqm3k", false}, + } + + for _, tc := range tt { + path := fmt.Sprintf("/metrics/%s", tc.routeVariable) + req, err := http.NewRequest("GET", path, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + + // To add the vars to the context, + // we need to create a router through which we can pass the request. + router := mux.NewRouter() + router.HandleFunc("/metrics/{type}", MetricsHandler) + router.ServeHTTP(rr, req) + + // In this case, our MetricsHandler returns a non-200 response + // for a route variable it doesn't know about. + if rr.Code == http.StatusOK && !tc.shouldPass { + t.Errorf("handler should have failed on routeVariable %s: got %v want %v", + tc.routeVariable, rr.Code, http.StatusOK) + } + } +} +``` + +## Full Example + +Here's a complete, runnable example of a small `mux` based server: + +```go +package main + +import ( + "net/http" + "log" + "github.com/gorilla/mux" +) + +func YourHandler(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Gorilla!\n")) +} + +func main() { + r := mux.NewRouter() + // Routes consist of a path and a handler function. + r.HandleFunc("/", YourHandler) + + // Bind to a port and pass our router in + log.Fatal(http.ListenAndServe(":8000", r)) +} +``` + +## License + +BSD licensed. See the LICENSE file for details. diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go new file mode 100644 index 00000000..80601351 --- /dev/null +++ b/vendor/github.com/gorilla/mux/doc.go @@ -0,0 +1,305 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package mux implements a request router and dispatcher. + +The name mux stands for "HTTP request multiplexer". Like the standard +http.ServeMux, mux.Router matches incoming requests against a list of +registered routes and calls a handler for the route that matches the URL +or other conditions. The main features are: + + - Requests can be matched based on URL host, path, path prefix, schemes, + header and query values, HTTP methods or using custom matchers. + - URL hosts, paths and query values can have variables with an optional + regular expression. + - Registered URLs can be built, or "reversed", which helps maintaining + references to resources. + - Routes can be used as subrouters: nested routes are only tested if the + parent route matches. This is useful to define groups of routes that + share common conditions like a host, a path prefix or other repeated + attributes. As a bonus, this optimizes request matching. + - It implements the http.Handler interface so it is compatible with the + standard http.ServeMux. + +Let's start registering a couple of URL paths and handlers: + + func main() { + r := mux.NewRouter() + r.HandleFunc("/", HomeHandler) + r.HandleFunc("/products", ProductsHandler) + r.HandleFunc("/articles", ArticlesHandler) + http.Handle("/", r) + } + +Here we register three routes mapping URL paths to handlers. This is +equivalent to how http.HandleFunc() works: if an incoming request URL matches +one of the paths, the corresponding handler is called passing +(http.ResponseWriter, *http.Request) as parameters. + +Paths can have variables. They are defined using the format {name} or +{name:pattern}. If a regular expression pattern is not defined, the matched +variable will be anything until the next slash. For example: + + r := mux.NewRouter() + r.HandleFunc("/products/{key}", ProductHandler) + r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) + r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) + +Groups can be used inside patterns, as long as they are non-capturing (?:re). For example: + + r.HandleFunc("/articles/{category}/{sort:(?:asc|desc|new)}", ArticlesCategoryHandler) + +The names are used to create a map of route variables which can be retrieved +calling mux.Vars(): + + vars := mux.Vars(request) + category := vars["category"] + +Note that if any capturing groups are present, mux will panic() during parsing. To prevent +this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to +"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably +when capturing groups were present. + +And this is all you need to know about the basic usage. More advanced options +are explained below. + +Routes can also be restricted to a domain or subdomain. Just define a host +pattern to be matched. They can also have variables: + + r := mux.NewRouter() + // Only matches if domain is "www.example.com". + r.Host("www.example.com") + // Matches a dynamic subdomain. + r.Host("{subdomain:[a-z]+}.domain.com") + +There are several other matchers that can be added. To match path prefixes: + + r.PathPrefix("/products/") + +...or HTTP methods: + + r.Methods("GET", "POST") + +...or URL schemes: + + r.Schemes("https") + +...or header values: + + r.Headers("X-Requested-With", "XMLHttpRequest") + +...or query values: + + r.Queries("key", "value") + +...or to use a custom matcher function: + + r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { + return r.ProtoMajor == 0 + }) + +...and finally, it is possible to combine several matchers in a single route: + + r.HandleFunc("/products", ProductsHandler). + Host("www.example.com"). + Methods("GET"). + Schemes("http") + +Setting the same matching conditions again and again can be boring, so we have +a way to group several routes that share the same requirements. +We call it "subrouting". + +For example, let's say we have several URLs that should only match when the +host is "www.example.com". Create a route for that host and get a "subrouter" +from it: + + r := mux.NewRouter() + s := r.Host("www.example.com").Subrouter() + +Then register routes in the subrouter: + + s.HandleFunc("/products/", ProductsHandler) + s.HandleFunc("/products/{key}", ProductHandler) + s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) + +The three URL paths we registered above will only be tested if the domain is +"www.example.com", because the subrouter is tested first. This is not +only convenient, but also optimizes request matching. You can create +subrouters combining any attribute matchers accepted by a route. + +Subrouters can be used to create domain or path "namespaces": you define +subrouters in a central place and then parts of the app can register its +paths relatively to a given subrouter. + +There's one more thing about subroutes. When a subrouter has a path prefix, +the inner routes use it as base for their paths: + + r := mux.NewRouter() + s := r.PathPrefix("/products").Subrouter() + // "/products/" + s.HandleFunc("/", ProductsHandler) + // "/products/{key}/" + s.HandleFunc("/{key}/", ProductHandler) + // "/products/{key}/details" + s.HandleFunc("/{key}/details", ProductDetailsHandler) + +Note that the path provided to PathPrefix() represents a "wildcard": calling +PathPrefix("/static/").Handler(...) means that the handler will be passed any +request that matches "/static/*". This makes it easy to serve static files with mux: + + func main() { + var dir string + + flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") + flag.Parse() + r := mux.NewRouter() + + // This will serve files under http://localhost:8000/static/ + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) + + srv := &http.Server{ + Handler: r, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) + } + +Now let's see how to build registered URLs. + +Routes can be named. All routes that define a name can have their URLs built, +or "reversed". We define a name calling Name() on a route. For example: + + r := mux.NewRouter() + r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). + Name("article") + +To build a URL, get the route and call the URL() method, passing a sequence of +key/value pairs for the route variables. For the previous route, we would do: + + url, err := r.Get("article").URL("category", "technology", "id", "42") + +...and the result will be a url.URL with the following path: + + "/articles/technology/42" + +This also works for host and query value variables: + + r := mux.NewRouter() + r.Host("{subdomain}.domain.com"). + Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). + HandlerFunc(ArticleHandler). + Name("article") + + // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" + url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42", + "filter", "gorilla") + +All variables defined in the route are required, and their values must +conform to the corresponding patterns. These requirements guarantee that a +generated URL will always match a registered route -- the only exception is +for explicitly defined "build-only" routes which never match. + +Regex support also exists for matching Headers within a route. For example, we could do: + + r.HeadersRegexp("Content-Type", "application/(text|json)") + +...and the route will match both requests with a Content-Type of `application/json` as well as +`application/text` + +There's also a way to build only the URL host or path for a route: +use the methods URLHost() or URLPath() instead. For the previous route, +we would do: + + // "http://news.domain.com/" + host, err := r.Get("article").URLHost("subdomain", "news") + + // "/articles/technology/42" + path, err := r.Get("article").URLPath("category", "technology", "id", "42") + +And if you use subrouters, host and path defined separately can be built +as well: + + r := mux.NewRouter() + s := r.Host("{subdomain}.domain.com").Subrouter() + s.Path("/articles/{category}/{id:[0-9]+}"). + HandlerFunc(ArticleHandler). + Name("article") + + // "http://news.domain.com/articles/technology/42" + url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42") + +Mux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking. + + type MiddlewareFunc func(http.Handler) http.Handler + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created). + +A very basic middleware which logs the URI of the request being handled could be written as: + + func simpleMw(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) + } + +Middlewares can be added to a router using `Router.Use()`: + + r := mux.NewRouter() + r.HandleFunc("/", handler) + r.Use(simpleMw) + +A more complex authentication middleware, which maps session token to users, could be written as: + + // Define our struct + type authenticationMiddleware struct { + tokenUsers map[string]string + } + + // Initialize it somewhere + func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" + } + + // Middleware function, which will be called for each request + func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + next.ServeHTTP(w, r) + } else { + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) + } + + r := mux.NewRouter() + r.HandleFunc("/", handler) + + amw := authenticationMiddleware{tokenUsers: make(map[string]string)} + amw.Populate() + + r.Use(amw.Middleware) + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. +*/ +package mux diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go new file mode 100644 index 00000000..cb51c565 --- /dev/null +++ b/vendor/github.com/gorilla/mux/middleware.go @@ -0,0 +1,74 @@ +package mux + +import ( + "net/http" + "strings" +) + +// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler. +// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed +// to it, and then calls the handler passed as parameter to the MiddlewareFunc. +type MiddlewareFunc func(http.Handler) http.Handler + +// middleware interface is anything which implements a MiddlewareFunc named Middleware. +type middleware interface { + Middleware(handler http.Handler) http.Handler +} + +// Middleware allows MiddlewareFunc to implement the middleware interface. +func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler { + return mw(handler) +} + +// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. +func (r *Router) Use(mwf ...MiddlewareFunc) { + for _, fn := range mwf { + r.middlewares = append(r.middlewares, fn) + } +} + +// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. +func (r *Router) useInterface(mw middleware) { + r.middlewares = append(r.middlewares, mw) +} + +// CORSMethodMiddleware automatically sets the Access-Control-Allow-Methods response header +// on requests for routes that have an OPTIONS method matcher to all the method matchers on +// the route. Routes that do not explicitly handle OPTIONS requests will not be processed +// by the middleware. See examples for usage. +func CORSMethodMiddleware(r *Router) MiddlewareFunc { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + allMethods, err := getAllMethodsForRoute(r, req) + if err == nil { + for _, v := range allMethods { + if v == http.MethodOptions { + w.Header().Set("Access-Control-Allow-Methods", strings.Join(allMethods, ",")) + } + } + } + + next.ServeHTTP(w, req) + }) + } +} + +// getAllMethodsForRoute returns all the methods from method matchers matching a given +// request. +func getAllMethodsForRoute(r *Router, req *http.Request) ([]string, error) { + var allMethods []string + + for _, route := range r.routes { + var match RouteMatch + if route.Match(req, &match) || match.MatchErr == ErrMethodMismatch { + methods, err := route.GetMethods() + if err != nil { + return nil, err + } + + allMethods = append(allMethods, methods...) + } + } + + return allMethods, nil +} diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go new file mode 100644 index 00000000..1e089906 --- /dev/null +++ b/vendor/github.com/gorilla/mux/mux.go @@ -0,0 +1,608 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "context" + "errors" + "fmt" + "net/http" + "path" + "regexp" +) + +var ( + // ErrMethodMismatch is returned when the method in the request does not match + // the method defined against the route. + ErrMethodMismatch = errors.New("method is not allowed") + // ErrNotFound is returned when no route match is found. + ErrNotFound = errors.New("no matching route was found") +) + +// NewRouter returns a new router instance. +func NewRouter() *Router { + return &Router{namedRoutes: make(map[string]*Route)} +} + +// Router registers routes to be matched and dispatches a handler. +// +// It implements the http.Handler interface, so it can be registered to serve +// requests: +// +// var router = mux.NewRouter() +// +// func main() { +// http.Handle("/", router) +// } +// +// Or, for Google App Engine, register it in a init() function: +// +// func init() { +// http.Handle("/", router) +// } +// +// This will send all incoming requests to the router. +type Router struct { + // Configurable Handler to be used when no route matches. + // This can be used to render your own 404 Not Found errors. + NotFoundHandler http.Handler + + // Configurable Handler to be used when the request method does not match the route. + // This can be used to render your own 405 Method Not Allowed errors. + MethodNotAllowedHandler http.Handler + + // Routes to be matched, in order. + routes []*Route + + // Routes by name for URL building. + namedRoutes map[string]*Route + + // If true, do not clear the request context after handling the request. + // + // Deprecated: No effect, since the context is stored on the request itself. + KeepContext bool + + // Slice of middlewares to be called after a match is found + middlewares []middleware + + // configuration shared with `Route` + routeConf +} + +// common route configuration shared between `Router` and `Route` +type routeConf struct { + // If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to" + useEncodedPath bool + + // If true, when the path pattern is "/path/", accessing "/path" will + // redirect to the former and vice versa. + strictSlash bool + + // If true, when the path pattern is "/path//to", accessing "/path//to" + // will not redirect + skipClean bool + + // Manager for the variables from host and path. + regexp routeRegexpGroup + + // List of matchers. + matchers []matcher + + // The scheme used when building URLs. + buildScheme string + + buildVarsFunc BuildVarsFunc +} + +// returns an effective deep copy of `routeConf` +func copyRouteConf(r routeConf) routeConf { + c := r + + if r.regexp.path != nil { + c.regexp.path = copyRouteRegexp(r.regexp.path) + } + + if r.regexp.host != nil { + c.regexp.host = copyRouteRegexp(r.regexp.host) + } + + c.regexp.queries = make([]*routeRegexp, 0, len(r.regexp.queries)) + for _, q := range r.regexp.queries { + c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q)) + } + + c.matchers = make([]matcher, len(r.matchers)) + copy(c.matchers, r.matchers) + + return c +} + +func copyRouteRegexp(r *routeRegexp) *routeRegexp { + c := *r + return &c +} + +// Match attempts to match the given request against the router's registered routes. +// +// If the request matches a route of this router or one of its subrouters the Route, +// Handler, and Vars fields of the the match argument are filled and this function +// returns true. +// +// If the request does not match any of this router's or its subrouters' routes +// then this function returns false. If available, a reason for the match failure +// will be filled in the match argument's MatchErr field. If the match failure type +// (eg: not found) has a registered handler, the handler is assigned to the Handler +// field of the match argument. +func (r *Router) Match(req *http.Request, match *RouteMatch) bool { + for _, route := range r.routes { + if route.Match(req, match) { + // Build middleware chain if no error was found + if match.MatchErr == nil { + for i := len(r.middlewares) - 1; i >= 0; i-- { + match.Handler = r.middlewares[i].Middleware(match.Handler) + } + } + return true + } + } + + if match.MatchErr == ErrMethodMismatch { + if r.MethodNotAllowedHandler != nil { + match.Handler = r.MethodNotAllowedHandler + return true + } + + return false + } + + // Closest match for a router (includes sub-routers) + if r.NotFoundHandler != nil { + match.Handler = r.NotFoundHandler + match.MatchErr = ErrNotFound + return true + } + + match.MatchErr = ErrNotFound + return false +} + +// ServeHTTP dispatches the handler registered in the matched route. +// +// When there is a match, the route variables can be retrieved calling +// mux.Vars(request). +func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if !r.skipClean { + path := req.URL.Path + if r.useEncodedPath { + path = req.URL.EscapedPath() + } + // Clean path to canonical form and redirect. + if p := cleanPath(path); p != path { + + // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query. + // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: + // http://code.google.com/p/go/issues/detail?id=5252 + url := *req.URL + url.Path = p + p = url.String() + + w.Header().Set("Location", p) + w.WriteHeader(http.StatusMovedPermanently) + return + } + } + var match RouteMatch + var handler http.Handler + if r.Match(req, &match) { + handler = match.Handler + req = requestWithVars(req, match.Vars) + req = requestWithRoute(req, match.Route) + } + + if handler == nil && match.MatchErr == ErrMethodMismatch { + handler = methodNotAllowedHandler() + } + + if handler == nil { + handler = http.NotFoundHandler() + } + + handler.ServeHTTP(w, req) +} + +// Get returns a route registered with the given name. +func (r *Router) Get(name string) *Route { + return r.namedRoutes[name] +} + +// GetRoute returns a route registered with the given name. This method +// was renamed to Get() and remains here for backwards compatibility. +func (r *Router) GetRoute(name string) *Route { + return r.namedRoutes[name] +} + +// StrictSlash defines the trailing slash behavior for new routes. The initial +// value is false. +// +// When true, if the route path is "/path/", accessing "/path" will perform a redirect +// to the former and vice versa. In other words, your application will always +// see the path as specified in the route. +// +// When false, if the route path is "/path", accessing "/path/" will not match +// this route and vice versa. +// +// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for +// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed +// request will be made as a GET by most clients. Use middleware or client settings +// to modify this behaviour as needed. +// +// Special case: when a route sets a path prefix using the PathPrefix() method, +// strict slash is ignored for that route because the redirect behavior can't +// be determined from a prefix alone. However, any subrouters created from that +// route inherit the original StrictSlash setting. +func (r *Router) StrictSlash(value bool) *Router { + r.strictSlash = value + return r +} + +// SkipClean defines the path cleaning behaviour for new routes. The initial +// value is false. Users should be careful about which routes are not cleaned +// +// When true, if the route path is "/path//to", it will remain with the double +// slash. This is helpful if you have a route like: /fetch/http://xkcd.com/534/ +// +// When false, the path will be cleaned, so /fetch/http://xkcd.com/534/ will +// become /fetch/http/xkcd.com/534 +func (r *Router) SkipClean(value bool) *Router { + r.skipClean = value + return r +} + +// UseEncodedPath tells the router to match the encoded original path +// to the routes. +// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to". +// +// If not called, the router will match the unencoded path to the routes. +// For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to" +func (r *Router) UseEncodedPath() *Router { + r.useEncodedPath = true + return r +} + +// ---------------------------------------------------------------------------- +// Route factories +// ---------------------------------------------------------------------------- + +// NewRoute registers an empty route. +func (r *Router) NewRoute() *Route { + // initialize a route with a copy of the parent router's configuration + route := &Route{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes} + r.routes = append(r.routes, route) + return route +} + +// Name registers a new route with a name. +// See Route.Name(). +func (r *Router) Name(name string) *Route { + return r.NewRoute().Name(name) +} + +// Handle registers a new route with a matcher for the URL path. +// See Route.Path() and Route.Handler(). +func (r *Router) Handle(path string, handler http.Handler) *Route { + return r.NewRoute().Path(path).Handler(handler) +} + +// HandleFunc registers a new route with a matcher for the URL path. +// See Route.Path() and Route.HandlerFunc(). +func (r *Router) HandleFunc(path string, f func(http.ResponseWriter, + *http.Request)) *Route { + return r.NewRoute().Path(path).HandlerFunc(f) +} + +// Headers registers a new route with a matcher for request header values. +// See Route.Headers(). +func (r *Router) Headers(pairs ...string) *Route { + return r.NewRoute().Headers(pairs...) +} + +// Host registers a new route with a matcher for the URL host. +// See Route.Host(). +func (r *Router) Host(tpl string) *Route { + return r.NewRoute().Host(tpl) +} + +// MatcherFunc registers a new route with a custom matcher function. +// See Route.MatcherFunc(). +func (r *Router) MatcherFunc(f MatcherFunc) *Route { + return r.NewRoute().MatcherFunc(f) +} + +// Methods registers a new route with a matcher for HTTP methods. +// See Route.Methods(). +func (r *Router) Methods(methods ...string) *Route { + return r.NewRoute().Methods(methods...) +} + +// Path registers a new route with a matcher for the URL path. +// See Route.Path(). +func (r *Router) Path(tpl string) *Route { + return r.NewRoute().Path(tpl) +} + +// PathPrefix registers a new route with a matcher for the URL path prefix. +// See Route.PathPrefix(). +func (r *Router) PathPrefix(tpl string) *Route { + return r.NewRoute().PathPrefix(tpl) +} + +// Queries registers a new route with a matcher for URL query values. +// See Route.Queries(). +func (r *Router) Queries(pairs ...string) *Route { + return r.NewRoute().Queries(pairs...) +} + +// Schemes registers a new route with a matcher for URL schemes. +// See Route.Schemes(). +func (r *Router) Schemes(schemes ...string) *Route { + return r.NewRoute().Schemes(schemes...) +} + +// BuildVarsFunc registers a new route with a custom function for modifying +// route variables before building a URL. +func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route { + return r.NewRoute().BuildVarsFunc(f) +} + +// Walk walks the router and all its sub-routers, calling walkFn for each route +// in the tree. The routes are walked in the order they were added. Sub-routers +// are explored depth-first. +func (r *Router) Walk(walkFn WalkFunc) error { + return r.walk(walkFn, []*Route{}) +} + +// SkipRouter is used as a return value from WalkFuncs to indicate that the +// router that walk is about to descend down to should be skipped. +var SkipRouter = errors.New("skip this router") + +// WalkFunc is the type of the function called for each route visited by Walk. +// At every invocation, it is given the current route, and the current router, +// and a list of ancestor routes that lead to the current route. +type WalkFunc func(route *Route, router *Router, ancestors []*Route) error + +func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { + for _, t := range r.routes { + err := walkFn(t, r, ancestors) + if err == SkipRouter { + continue + } + if err != nil { + return err + } + for _, sr := range t.matchers { + if h, ok := sr.(*Router); ok { + ancestors = append(ancestors, t) + err := h.walk(walkFn, ancestors) + if err != nil { + return err + } + ancestors = ancestors[:len(ancestors)-1] + } + } + if h, ok := t.handler.(*Router); ok { + ancestors = append(ancestors, t) + err := h.walk(walkFn, ancestors) + if err != nil { + return err + } + ancestors = ancestors[:len(ancestors)-1] + } + } + return nil +} + +// ---------------------------------------------------------------------------- +// Context +// ---------------------------------------------------------------------------- + +// RouteMatch stores information about a matched route. +type RouteMatch struct { + Route *Route + Handler http.Handler + Vars map[string]string + + // MatchErr is set to appropriate matching error + // It is set to ErrMethodMismatch if there is a mismatch in + // the request method and route method + MatchErr error +} + +type contextKey int + +const ( + varsKey contextKey = iota + routeKey +) + +// Vars returns the route variables for the current request, if any. +func Vars(r *http.Request) map[string]string { + if rv := r.Context().Value(varsKey); rv != nil { + return rv.(map[string]string) + } + return nil +} + +// CurrentRoute returns the matched route for the current request, if any. +// This only works when called inside the handler of the matched route +// because the matched route is stored in the request context which is cleared +// after the handler returns. +func CurrentRoute(r *http.Request) *Route { + if rv := r.Context().Value(routeKey); rv != nil { + return rv.(*Route) + } + return nil +} + +func requestWithVars(r *http.Request, vars map[string]string) *http.Request { + ctx := context.WithValue(r.Context(), varsKey, vars) + return r.WithContext(ctx) +} + +func requestWithRoute(r *http.Request, route *Route) *http.Request { + ctx := context.WithValue(r.Context(), routeKey, route) + return r.WithContext(ctx) +} + +// ---------------------------------------------------------------------------- +// Helpers +// ---------------------------------------------------------------------------- + +// cleanPath returns the canonical path for p, eliminating . and .. elements. +// Borrowed from the net/http package. +func cleanPath(p string) string { + if p == "" { + return "/" + } + if p[0] != '/' { + p = "/" + p + } + np := path.Clean(p) + // path.Clean removes trailing slash except for root; + // put the trailing slash back if necessary. + if p[len(p)-1] == '/' && np != "/" { + np += "/" + } + + return np +} + +// uniqueVars returns an error if two slices contain duplicated strings. +func uniqueVars(s1, s2 []string) error { + for _, v1 := range s1 { + for _, v2 := range s2 { + if v1 == v2 { + return fmt.Errorf("mux: duplicated route variable %q", v2) + } + } + } + return nil +} + +// checkPairs returns the count of strings passed in, and an error if +// the count is not an even number. +func checkPairs(pairs ...string) (int, error) { + length := len(pairs) + if length%2 != 0 { + return length, fmt.Errorf( + "mux: number of parameters must be multiple of 2, got %v", pairs) + } + return length, nil +} + +// mapFromPairsToString converts variadic string parameters to a +// string to string map. +func mapFromPairsToString(pairs ...string) (map[string]string, error) { + length, err := checkPairs(pairs...) + if err != nil { + return nil, err + } + m := make(map[string]string, length/2) + for i := 0; i < length; i += 2 { + m[pairs[i]] = pairs[i+1] + } + return m, nil +} + +// mapFromPairsToRegex converts variadic string parameters to a +// string to regex map. +func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) { + length, err := checkPairs(pairs...) + if err != nil { + return nil, err + } + m := make(map[string]*regexp.Regexp, length/2) + for i := 0; i < length; i += 2 { + regex, err := regexp.Compile(pairs[i+1]) + if err != nil { + return nil, err + } + m[pairs[i]] = regex + } + return m, nil +} + +// matchInArray returns true if the given string value is in the array. +func matchInArray(arr []string, value string) bool { + for _, v := range arr { + if v == value { + return true + } + } + return false +} + +// matchMapWithString returns true if the given key/value pairs exist in a given map. +func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool { + for k, v := range toCheck { + // Check if key exists. + if canonicalKey { + k = http.CanonicalHeaderKey(k) + } + if values := toMatch[k]; values == nil { + return false + } else if v != "" { + // If value was defined as an empty string we only check that the + // key exists. Otherwise we also check for equality. + valueExists := false + for _, value := range values { + if v == value { + valueExists = true + break + } + } + if !valueExists { + return false + } + } + } + return true +} + +// matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against +// the given regex +func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool { + for k, v := range toCheck { + // Check if key exists. + if canonicalKey { + k = http.CanonicalHeaderKey(k) + } + if values := toMatch[k]; values == nil { + return false + } else if v != nil { + // If value was defined as an empty string we only check that the + // key exists. Otherwise we also check for equality. + valueExists := false + for _, value := range values { + if v.MatchString(value) { + valueExists = true + break + } + } + if !valueExists { + return false + } + } + } + return true +} + +// methodNotAllowed replies to the request with an HTTP status code 405. +func methodNotAllowed(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusMethodNotAllowed) +} + +// methodNotAllowedHandler returns a simple request handler +// that replies to each request with a status code 405. +func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) } diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go new file mode 100644 index 00000000..5d05cfa0 --- /dev/null +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -0,0 +1,388 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "bytes" + "fmt" + "net/http" + "net/url" + "regexp" + "strconv" + "strings" +) + +type routeRegexpOptions struct { + strictSlash bool + useEncodedPath bool +} + +type regexpType int + +const ( + regexpTypePath regexpType = iota + regexpTypeHost + regexpTypePrefix + regexpTypeQuery +) + +// newRouteRegexp parses a route template and returns a routeRegexp, +// used to match a host, a path or a query string. +// +// It will extract named variables, assemble a regexp to be matched, create +// a "reverse" template to build URLs and compile regexps to validate variable +// values used in URL building. +// +// Previously we accepted only Python-like identifiers for variable +// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that +// name and pattern can't be empty, and names can't contain a colon. +func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) { + // Check if it is well-formed. + idxs, errBraces := braceIndices(tpl) + if errBraces != nil { + return nil, errBraces + } + // Backup the original. + template := tpl + // Now let's parse it. + defaultPattern := "[^/]+" + if typ == regexpTypeQuery { + defaultPattern = ".*" + } else if typ == regexpTypeHost { + defaultPattern = "[^.]+" + } + // Only match strict slash if not matching + if typ != regexpTypePath { + options.strictSlash = false + } + // Set a flag for strictSlash. + endSlash := false + if options.strictSlash && strings.HasSuffix(tpl, "/") { + tpl = tpl[:len(tpl)-1] + endSlash = true + } + varsN := make([]string, len(idxs)/2) + varsR := make([]*regexp.Regexp, len(idxs)/2) + pattern := bytes.NewBufferString("") + pattern.WriteByte('^') + reverse := bytes.NewBufferString("") + var end int + var err error + for i := 0; i < len(idxs); i += 2 { + // Set all values we are interested in. + raw := tpl[end:idxs[i]] + end = idxs[i+1] + parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2) + name := parts[0] + patt := defaultPattern + if len(parts) == 2 { + patt = parts[1] + } + // Name or pattern can't be empty. + if name == "" || patt == "" { + return nil, fmt.Errorf("mux: missing name or pattern in %q", + tpl[idxs[i]:end]) + } + // Build the regexp pattern. + fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(i/2), patt) + + // Build the reverse template. + fmt.Fprintf(reverse, "%s%%s", raw) + + // Append variable name and compiled pattern. + varsN[i/2] = name + varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) + if err != nil { + return nil, err + } + } + // Add the remaining. + raw := tpl[end:] + pattern.WriteString(regexp.QuoteMeta(raw)) + if options.strictSlash { + pattern.WriteString("[/]?") + } + if typ == regexpTypeQuery { + // Add the default pattern if the query value is empty + if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { + pattern.WriteString(defaultPattern) + } + } + if typ != regexpTypePrefix { + pattern.WriteByte('$') + } + + var wildcardHostPort bool + if typ == regexpTypeHost { + if !strings.Contains(pattern.String(), ":") { + wildcardHostPort = true + } + } + reverse.WriteString(raw) + if endSlash { + reverse.WriteByte('/') + } + // Compile full regexp. + reg, errCompile := regexp.Compile(pattern.String()) + if errCompile != nil { + return nil, errCompile + } + + // Check for capturing groups which used to work in older versions + if reg.NumSubexp() != len(idxs)/2 { + panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) + + "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)") + } + + // Done! + return &routeRegexp{ + template: template, + regexpType: typ, + options: options, + regexp: reg, + reverse: reverse.String(), + varsN: varsN, + varsR: varsR, + wildcardHostPort: wildcardHostPort, + }, nil +} + +// routeRegexp stores a regexp to match a host or path and information to +// collect and validate route variables. +type routeRegexp struct { + // The unmodified template. + template string + // The type of match + regexpType regexpType + // Options for matching + options routeRegexpOptions + // Expanded regexp. + regexp *regexp.Regexp + // Reverse template. + reverse string + // Variable names. + varsN []string + // Variable regexps (validators). + varsR []*regexp.Regexp + // Wildcard host-port (no strict port match in hostname) + wildcardHostPort bool +} + +// Match matches the regexp against the URL host or path. +func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { + if r.regexpType == regexpTypeHost { + host := getHost(req) + if r.wildcardHostPort { + // Don't be strict on the port match + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } + } + return r.regexp.MatchString(host) + } + + if r.regexpType == regexpTypeQuery { + return r.matchQueryString(req) + } + path := req.URL.Path + if r.options.useEncodedPath { + path = req.URL.EscapedPath() + } + return r.regexp.MatchString(path) +} + +// url builds a URL part using the given values. +func (r *routeRegexp) url(values map[string]string) (string, error) { + urlValues := make([]interface{}, len(r.varsN)) + for k, v := range r.varsN { + value, ok := values[v] + if !ok { + return "", fmt.Errorf("mux: missing route variable %q", v) + } + if r.regexpType == regexpTypeQuery { + value = url.QueryEscape(value) + } + urlValues[k] = value + } + rv := fmt.Sprintf(r.reverse, urlValues...) + if !r.regexp.MatchString(rv) { + // The URL is checked against the full regexp, instead of checking + // individual variables. This is faster but to provide a good error + // message, we check individual regexps if the URL doesn't match. + for k, v := range r.varsN { + if !r.varsR[k].MatchString(values[v]) { + return "", fmt.Errorf( + "mux: variable %q doesn't match, expected %q", values[v], + r.varsR[k].String()) + } + } + } + return rv, nil +} + +// getURLQuery returns a single query parameter from a request URL. +// For a URL with foo=bar&baz=ding, we return only the relevant key +// value pair for the routeRegexp. +func (r *routeRegexp) getURLQuery(req *http.Request) string { + if r.regexpType != regexpTypeQuery { + return "" + } + templateKey := strings.SplitN(r.template, "=", 2)[0] + val, ok := findFirstQueryKey(req.URL.RawQuery, templateKey) + if ok { + return templateKey + "=" + val + } + return "" +} + +// findFirstQueryKey returns the same result as (*url.URL).Query()[key][0]. +// If key was not found, empty string and false is returned. +func findFirstQueryKey(rawQuery, key string) (value string, ok bool) { + query := []byte(rawQuery) + for len(query) > 0 { + foundKey := query + if i := bytes.IndexAny(foundKey, "&;"); i >= 0 { + foundKey, query = foundKey[:i], foundKey[i+1:] + } else { + query = query[:0] + } + if len(foundKey) == 0 { + continue + } + var value []byte + if i := bytes.IndexByte(foundKey, '='); i >= 0 { + foundKey, value = foundKey[:i], foundKey[i+1:] + } + if len(foundKey) < len(key) { + // Cannot possibly be key. + continue + } + keyString, err := url.QueryUnescape(string(foundKey)) + if err != nil { + continue + } + if keyString != key { + continue + } + valueString, err := url.QueryUnescape(string(value)) + if err != nil { + continue + } + return valueString, true + } + return "", false +} + +func (r *routeRegexp) matchQueryString(req *http.Request) bool { + return r.regexp.MatchString(r.getURLQuery(req)) +} + +// braceIndices returns the first level curly brace indices from a string. +// It returns an error in case of unbalanced braces. +func braceIndices(s string) ([]int, error) { + var level, idx int + var idxs []int + for i := 0; i < len(s); i++ { + switch s[i] { + case '{': + if level++; level == 1 { + idx = i + } + case '}': + if level--; level == 0 { + idxs = append(idxs, idx, i+1) + } else if level < 0 { + return nil, fmt.Errorf("mux: unbalanced braces in %q", s) + } + } + } + if level != 0 { + return nil, fmt.Errorf("mux: unbalanced braces in %q", s) + } + return idxs, nil +} + +// varGroupName builds a capturing group name for the indexed variable. +func varGroupName(idx int) string { + return "v" + strconv.Itoa(idx) +} + +// ---------------------------------------------------------------------------- +// routeRegexpGroup +// ---------------------------------------------------------------------------- + +// routeRegexpGroup groups the route matchers that carry variables. +type routeRegexpGroup struct { + host *routeRegexp + path *routeRegexp + queries []*routeRegexp +} + +// setMatch extracts the variables from the URL once a route matches. +func (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { + // Store host variables. + if v.host != nil { + host := getHost(req) + if v.host.wildcardHostPort { + // Don't be strict on the port match + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } + } + matches := v.host.regexp.FindStringSubmatchIndex(host) + if len(matches) > 0 { + extractVars(host, matches, v.host.varsN, m.Vars) + } + } + path := req.URL.Path + if r.useEncodedPath { + path = req.URL.EscapedPath() + } + // Store path variables. + if v.path != nil { + matches := v.path.regexp.FindStringSubmatchIndex(path) + if len(matches) > 0 { + extractVars(path, matches, v.path.varsN, m.Vars) + // Check if we should redirect. + if v.path.options.strictSlash { + p1 := strings.HasSuffix(path, "/") + p2 := strings.HasSuffix(v.path.template, "/") + if p1 != p2 { + u, _ := url.Parse(req.URL.String()) + if p1 { + u.Path = u.Path[:len(u.Path)-1] + } else { + u.Path += "/" + } + m.Handler = http.RedirectHandler(u.String(), http.StatusMovedPermanently) + } + } + } + } + // Store query string variables. + for _, q := range v.queries { + queryURL := q.getURLQuery(req) + matches := q.regexp.FindStringSubmatchIndex(queryURL) + if len(matches) > 0 { + extractVars(queryURL, matches, q.varsN, m.Vars) + } + } +} + +// getHost tries its best to return the request host. +// According to section 14.23 of RFC 2616 the Host header +// can include the port number if the default value of 80 is not used. +func getHost(r *http.Request) string { + if r.URL.IsAbs() { + return r.URL.Host + } + return r.Host +} + +func extractVars(input string, matches []int, names []string, output map[string]string) { + for i, name := range names { + output[name] = input[matches[2*i+2]:matches[2*i+3]] + } +} diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go new file mode 100644 index 00000000..e8f11df2 --- /dev/null +++ b/vendor/github.com/gorilla/mux/route.go @@ -0,0 +1,765 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "errors" + "fmt" + "net/http" + "net/url" + "regexp" + "strings" +) + +// Route stores information to match a request and build URLs. +type Route struct { + // Request handler for the route. + handler http.Handler + // If true, this route never matches: it is only used to build URLs. + buildOnly bool + // The name used to build URLs. + name string + // Error resulted from building a route. + err error + + // "global" reference to all named routes + namedRoutes map[string]*Route + + // config possibly passed in from `Router` + routeConf +} + +// SkipClean reports whether path cleaning is enabled for this route via +// Router.SkipClean. +func (r *Route) SkipClean() bool { + return r.skipClean +} + +// Match matches the route against the request. +func (r *Route) Match(req *http.Request, match *RouteMatch) bool { + if r.buildOnly || r.err != nil { + return false + } + + var matchErr error + + // Match everything. + for _, m := range r.matchers { + if matched := m.Match(req, match); !matched { + if _, ok := m.(methodMatcher); ok { + matchErr = ErrMethodMismatch + continue + } + + // Ignore ErrNotFound errors. These errors arise from match call + // to Subrouters. + // + // This prevents subsequent matching subrouters from failing to + // run middleware. If not ignored, the middleware would see a + // non-nil MatchErr and be skipped, even when there was a + // matching route. + if match.MatchErr == ErrNotFound { + match.MatchErr = nil + } + + matchErr = nil // nolint:ineffassign + return false + } else { + // Multiple routes may share the same path but use different HTTP methods. For instance: + // Route 1: POST "/users/{id}". + // Route 2: GET "/users/{id}", parameters: "id": "[0-9]+". + // + // The router must handle these cases correctly. For a GET request to "/users/abc" with "id" as "-2", + // The router should return a "Not Found" error as no route fully matches this request. + if match.MatchErr == ErrMethodMismatch { + match.MatchErr = nil + } + } + } + + if matchErr != nil { + match.MatchErr = matchErr + return false + } + + if match.MatchErr == ErrMethodMismatch && r.handler != nil { + // We found a route which matches request method, clear MatchErr + match.MatchErr = nil + // Then override the mis-matched handler + match.Handler = r.handler + } + + // Yay, we have a match. Let's collect some info about it. + if match.Route == nil { + match.Route = r + } + if match.Handler == nil { + match.Handler = r.handler + } + if match.Vars == nil { + match.Vars = make(map[string]string) + } + + // Set variables. + r.regexp.setMatch(req, match, r) + return true +} + +// ---------------------------------------------------------------------------- +// Route attributes +// ---------------------------------------------------------------------------- + +// GetError returns an error resulted from building the route, if any. +func (r *Route) GetError() error { + return r.err +} + +// BuildOnly sets the route to never match: it is only used to build URLs. +func (r *Route) BuildOnly() *Route { + r.buildOnly = true + return r +} + +// Handler -------------------------------------------------------------------- + +// Handler sets a handler for the route. +func (r *Route) Handler(handler http.Handler) *Route { + if r.err == nil { + r.handler = handler + } + return r +} + +// HandlerFunc sets a handler function for the route. +func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route { + return r.Handler(http.HandlerFunc(f)) +} + +// GetHandler returns the handler for the route, if any. +func (r *Route) GetHandler() http.Handler { + return r.handler +} + +// Name ----------------------------------------------------------------------- + +// Name sets the name for the route, used to build URLs. +// It is an error to call Name more than once on a route. +func (r *Route) Name(name string) *Route { + if r.name != "" { + r.err = fmt.Errorf("mux: route already has name %q, can't set %q", + r.name, name) + } + if r.err == nil { + r.name = name + r.namedRoutes[name] = r + } + return r +} + +// GetName returns the name for the route, if any. +func (r *Route) GetName() string { + return r.name +} + +// ---------------------------------------------------------------------------- +// Matchers +// ---------------------------------------------------------------------------- + +// matcher types try to match a request. +type matcher interface { + Match(*http.Request, *RouteMatch) bool +} + +// addMatcher adds a matcher to the route. +func (r *Route) addMatcher(m matcher) *Route { + if r.err == nil { + r.matchers = append(r.matchers, m) + } + return r +} + +// addRegexpMatcher adds a host or path matcher and builder to a route. +func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { + if r.err != nil { + return r.err + } + if typ == regexpTypePath || typ == regexpTypePrefix { + if len(tpl) > 0 && tpl[0] != '/' { + return fmt.Errorf("mux: path must start with a slash, got %q", tpl) + } + if r.regexp.path != nil { + tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl + } + } + rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{ + strictSlash: r.strictSlash, + useEncodedPath: r.useEncodedPath, + }) + if err != nil { + return err + } + for _, q := range r.regexp.queries { + if err = uniqueVars(rr.varsN, q.varsN); err != nil { + return err + } + } + if typ == regexpTypeHost { + if r.regexp.path != nil { + if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { + return err + } + } + r.regexp.host = rr + } else { + if r.regexp.host != nil { + if err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil { + return err + } + } + if typ == regexpTypeQuery { + r.regexp.queries = append(r.regexp.queries, rr) + } else { + r.regexp.path = rr + } + } + r.addMatcher(rr) + return nil +} + +// Headers -------------------------------------------------------------------- + +// headerMatcher matches the request against header values. +type headerMatcher map[string]string + +func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { + return matchMapWithString(m, r.Header, true) +} + +// Headers adds a matcher for request header values. +// It accepts a sequence of key/value pairs to be matched. For example: +// +// r := mux.NewRouter().NewRoute() +// r.Headers("Content-Type", "application/json", +// "X-Requested-With", "XMLHttpRequest") +// +// The above route will only match if both request header values match. +// If the value is an empty string, it will match any value if the key is set. +func (r *Route) Headers(pairs ...string) *Route { + if r.err == nil { + var headers map[string]string + headers, r.err = mapFromPairsToString(pairs...) + return r.addMatcher(headerMatcher(headers)) + } + return r +} + +// headerRegexMatcher matches the request against the route given a regex for the header +type headerRegexMatcher map[string]*regexp.Regexp + +func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { + return matchMapWithRegex(m, r.Header, true) +} + +// HeadersRegexp accepts a sequence of key/value pairs, where the value has regex +// support. For example: +// +// r := mux.NewRouter().NewRoute() +// r.HeadersRegexp("Content-Type", "application/(text|json)", +// "X-Requested-With", "XMLHttpRequest") +// +// The above route will only match if both the request header matches both regular expressions. +// If the value is an empty string, it will match any value if the key is set. +// Use the start and end of string anchors (^ and $) to match an exact value. +func (r *Route) HeadersRegexp(pairs ...string) *Route { + if r.err == nil { + var headers map[string]*regexp.Regexp + headers, r.err = mapFromPairsToRegex(pairs...) + return r.addMatcher(headerRegexMatcher(headers)) + } + return r +} + +// Host ----------------------------------------------------------------------- + +// Host adds a matcher for the URL host. +// It accepts a template with zero or more URL variables enclosed by {}. +// Variables can define an optional regexp pattern to be matched: +// +// - {name} matches anything until the next dot. +// +// - {name:pattern} matches the given regexp pattern. +// +// For example: +// +// r := mux.NewRouter().NewRoute() +// r.Host("www.example.com") +// r.Host("{subdomain}.domain.com") +// r.Host("{subdomain:[a-z]+}.domain.com") +// +// Variable names must be unique in a given route. They can be retrieved +// calling mux.Vars(request). +func (r *Route) Host(tpl string) *Route { + r.err = r.addRegexpMatcher(tpl, regexpTypeHost) + return r +} + +// MatcherFunc ---------------------------------------------------------------- + +// MatcherFunc is the function signature used by custom matchers. +type MatcherFunc func(*http.Request, *RouteMatch) bool + +// Match returns the match for a given request. +func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool { + return m(r, match) +} + +// MatcherFunc adds a custom function to be used as request matcher. +func (r *Route) MatcherFunc(f MatcherFunc) *Route { + return r.addMatcher(f) +} + +// Methods -------------------------------------------------------------------- + +// methodMatcher matches the request against HTTP methods. +type methodMatcher []string + +func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool { + return matchInArray(m, r.Method) +} + +// Methods adds a matcher for HTTP methods. +// It accepts a sequence of one or more methods to be matched, e.g.: +// "GET", "POST", "PUT". +func (r *Route) Methods(methods ...string) *Route { + for k, v := range methods { + methods[k] = strings.ToUpper(v) + } + return r.addMatcher(methodMatcher(methods)) +} + +// Path ----------------------------------------------------------------------- + +// Path adds a matcher for the URL path. +// It accepts a template with zero or more URL variables enclosed by {}. The +// template must start with a "/". +// Variables can define an optional regexp pattern to be matched: +// +// - {name} matches anything until the next slash. +// +// - {name:pattern} matches the given regexp pattern. +// +// For example: +// +// r := mux.NewRouter().NewRoute() +// r.Path("/products/").Handler(ProductsHandler) +// r.Path("/products/{key}").Handler(ProductsHandler) +// r.Path("/articles/{category}/{id:[0-9]+}"). +// Handler(ArticleHandler) +// +// Variable names must be unique in a given route. They can be retrieved +// calling mux.Vars(request). +func (r *Route) Path(tpl string) *Route { + r.err = r.addRegexpMatcher(tpl, regexpTypePath) + return r +} + +// PathPrefix ----------------------------------------------------------------- + +// PathPrefix adds a matcher for the URL path prefix. This matches if the given +// template is a prefix of the full URL path. See Route.Path() for details on +// the tpl argument. +// +// Note that it does not treat slashes specially ("/foobar/" will be matched by +// the prefix "/foo") so you may want to use a trailing slash here. +// +// Also note that the setting of Router.StrictSlash() has no effect on routes +// with a PathPrefix matcher. +func (r *Route) PathPrefix(tpl string) *Route { + r.err = r.addRegexpMatcher(tpl, regexpTypePrefix) + return r +} + +// Query ---------------------------------------------------------------------- + +// Queries adds a matcher for URL query values. +// It accepts a sequence of key/value pairs. Values may define variables. +// For example: +// +// r := mux.NewRouter().NewRoute() +// r.Queries("foo", "bar", "id", "{id:[0-9]+}") +// +// The above route will only match if the URL contains the defined queries +// values, e.g.: ?foo=bar&id=42. +// +// If the value is an empty string, it will match any value if the key is set. +// +// Variables can define an optional regexp pattern to be matched: +// +// - {name} matches anything until the next slash. +// +// - {name:pattern} matches the given regexp pattern. +func (r *Route) Queries(pairs ...string) *Route { + length := len(pairs) + if length%2 != 0 { + r.err = fmt.Errorf( + "mux: number of parameters must be multiple of 2, got %v", pairs) + return nil + } + for i := 0; i < length; i += 2 { + if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], regexpTypeQuery); r.err != nil { + return r + } + } + + return r +} + +// Schemes -------------------------------------------------------------------- + +// schemeMatcher matches the request against URL schemes. +type schemeMatcher []string + +func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { + scheme := r.URL.Scheme + // https://golang.org/pkg/net/http/#Request + // "For [most] server requests, fields other than Path and RawQuery will be + // empty." + // Since we're an http muxer, the scheme is either going to be http or https + // though, so we can just set it based on the tls termination state. + if scheme == "" { + if r.TLS == nil { + scheme = "http" + } else { + scheme = "https" + } + } + return matchInArray(m, scheme) +} + +// Schemes adds a matcher for URL schemes. +// It accepts a sequence of schemes to be matched, e.g.: "http", "https". +// If the request's URL has a scheme set, it will be matched against. +// Generally, the URL scheme will only be set if a previous handler set it, +// such as the ProxyHeaders handler from gorilla/handlers. +// If unset, the scheme will be determined based on the request's TLS +// termination state. +// The first argument to Schemes will be used when constructing a route URL. +func (r *Route) Schemes(schemes ...string) *Route { + for k, v := range schemes { + schemes[k] = strings.ToLower(v) + } + if len(schemes) > 0 { + r.buildScheme = schemes[0] + } + return r.addMatcher(schemeMatcher(schemes)) +} + +// BuildVarsFunc -------------------------------------------------------------- + +// BuildVarsFunc is the function signature used by custom build variable +// functions (which can modify route variables before a route's URL is built). +type BuildVarsFunc func(map[string]string) map[string]string + +// BuildVarsFunc adds a custom function to be used to modify build variables +// before a route's URL is built. +func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { + if r.buildVarsFunc != nil { + // compose the old and new functions + old := r.buildVarsFunc + r.buildVarsFunc = func(m map[string]string) map[string]string { + return f(old(m)) + } + } else { + r.buildVarsFunc = f + } + return r +} + +// Subrouter ------------------------------------------------------------------ + +// Subrouter creates a subrouter for the route. +// +// It will test the inner routes only if the parent route matched. For example: +// +// r := mux.NewRouter().NewRoute() +// s := r.Host("www.example.com").Subrouter() +// s.HandleFunc("/products/", ProductsHandler) +// s.HandleFunc("/products/{key}", ProductHandler) +// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) +// +// Here, the routes registered in the subrouter won't be tested if the host +// doesn't match. +func (r *Route) Subrouter() *Router { + // initialize a subrouter with a copy of the parent route's configuration + router := &Router{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes} + r.addMatcher(router) + return router +} + +// ---------------------------------------------------------------------------- +// URL building +// ---------------------------------------------------------------------------- + +// URL builds a URL for the route. +// +// It accepts a sequence of key/value pairs for the route variables. For +// example, given this route: +// +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Name("article") +// +// ...a URL for it can be built using: +// +// url, err := r.Get("article").URL("category", "technology", "id", "42") +// +// ...which will return an url.URL with the following path: +// +// "/articles/technology/42" +// +// This also works for host variables: +// +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Host("{subdomain}.domain.com"). +// Name("article") +// +// // url.String() will be "http://news.domain.com/articles/technology/42" +// url, err := r.Get("article").URL("subdomain", "news", +// "category", "technology", +// "id", "42") +// +// The scheme of the resulting url will be the first argument that was passed to Schemes: +// +// // url.String() will be "https://example.com" +// r := mux.NewRouter().NewRoute() +// url, err := r.Host("example.com") +// .Schemes("https", "http").URL() +// +// All variables defined in the route are required, and their values must +// conform to the corresponding patterns. +func (r *Route) URL(pairs ...string) (*url.URL, error) { + if r.err != nil { + return nil, r.err + } + values, err := r.prepareVars(pairs...) + if err != nil { + return nil, err + } + var scheme, host, path string + queries := make([]string, 0, len(r.regexp.queries)) + if r.regexp.host != nil { + if host, err = r.regexp.host.url(values); err != nil { + return nil, err + } + scheme = "http" + if r.buildScheme != "" { + scheme = r.buildScheme + } + } + if r.regexp.path != nil { + if path, err = r.regexp.path.url(values); err != nil { + return nil, err + } + } + for _, q := range r.regexp.queries { + var query string + if query, err = q.url(values); err != nil { + return nil, err + } + queries = append(queries, query) + } + return &url.URL{ + Scheme: scheme, + Host: host, + Path: path, + RawQuery: strings.Join(queries, "&"), + }, nil +} + +// URLHost builds the host part of the URL for a route. See Route.URL(). +// +// The route must have a host defined. +func (r *Route) URLHost(pairs ...string) (*url.URL, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.host == nil { + return nil, errors.New("mux: route doesn't have a host") + } + values, err := r.prepareVars(pairs...) + if err != nil { + return nil, err + } + host, err := r.regexp.host.url(values) + if err != nil { + return nil, err + } + u := &url.URL{ + Scheme: "http", + Host: host, + } + if r.buildScheme != "" { + u.Scheme = r.buildScheme + } + return u, nil +} + +// URLPath builds the path part of the URL for a route. See Route.URL(). +// +// The route must have a path defined. +func (r *Route) URLPath(pairs ...string) (*url.URL, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.path == nil { + return nil, errors.New("mux: route doesn't have a path") + } + values, err := r.prepareVars(pairs...) + if err != nil { + return nil, err + } + path, err := r.regexp.path.url(values) + if err != nil { + return nil, err + } + return &url.URL{ + Path: path, + }, nil +} + +// GetPathTemplate returns the template used to build the +// route match. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define a path. +func (r *Route) GetPathTemplate() (string, error) { + if r.err != nil { + return "", r.err + } + if r.regexp.path == nil { + return "", errors.New("mux: route doesn't have a path") + } + return r.regexp.path.template, nil +} + +// GetPathRegexp returns the expanded regular expression used to match route path. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define a path. +func (r *Route) GetPathRegexp() (string, error) { + if r.err != nil { + return "", r.err + } + if r.regexp.path == nil { + return "", errors.New("mux: route does not have a path") + } + return r.regexp.path.regexp.String(), nil +} + +// GetQueriesRegexp returns the expanded regular expressions used to match the +// route queries. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not have queries. +func (r *Route) GetQueriesRegexp() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + queries := make([]string, 0, len(r.regexp.queries)) + for _, query := range r.regexp.queries { + queries = append(queries, query.regexp.String()) + } + return queries, nil +} + +// GetQueriesTemplates returns the templates used to build the +// query matching. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define queries. +func (r *Route) GetQueriesTemplates() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + queries := make([]string, 0, len(r.regexp.queries)) + for _, query := range r.regexp.queries { + queries = append(queries, query.template) + } + return queries, nil +} + +// GetMethods returns the methods the route matches against +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if route does not have methods. +func (r *Route) GetMethods() ([]string, error) { + if r.err != nil { + return nil, r.err + } + for _, m := range r.matchers { + if methods, ok := m.(methodMatcher); ok { + return []string(methods), nil + } + } + return nil, errors.New("mux: route doesn't have methods") +} + +// GetHostTemplate returns the template used to build the +// route match. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define a host. +func (r *Route) GetHostTemplate() (string, error) { + if r.err != nil { + return "", r.err + } + if r.regexp.host == nil { + return "", errors.New("mux: route doesn't have a host") + } + return r.regexp.host.template, nil +} + +// GetVarNames returns the names of all variables added by regexp matchers +// These can be used to know which route variables should be passed into r.URL() +func (r *Route) GetVarNames() ([]string, error) { + if r.err != nil { + return nil, r.err + } + var varNames []string + if r.regexp.host != nil { + varNames = append(varNames, r.regexp.host.varsN...) + } + if r.regexp.path != nil { + varNames = append(varNames, r.regexp.path.varsN...) + } + for _, regx := range r.regexp.queries { + varNames = append(varNames, regx.varsN...) + } + return varNames, nil +} + +// prepareVars converts the route variable pairs into a map. If the route has a +// BuildVarsFunc, it is invoked. +func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { + m, err := mapFromPairsToString(pairs...) + if err != nil { + return nil, err + } + return r.buildVars(m), nil +} + +func (r *Route) buildVars(m map[string]string) map[string]string { + if r.buildVarsFunc != nil { + m = r.buildVarsFunc(m) + } + return m +} diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go new file mode 100644 index 00000000..5f5c496d --- /dev/null +++ b/vendor/github.com/gorilla/mux/test_helpers.go @@ -0,0 +1,19 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import "net/http" + +// SetURLVars sets the URL variables for the given request, to be accessed via +// mux.Vars for testing route behaviour. Arguments are not modified, a shallow +// copy is returned. +// +// This API should only be used for testing purposes; it provides a way to +// inject variables into the request context. Alternatively, URL variables +// can be set by making a route that captures the required variables, +// starting a server and sending the request to that server. +func SetURLVars(r *http.Request, val map[string]string) *http.Request { + return requestWithVars(r, val) +} diff --git a/vendor/github.com/oapi-codegen/echo-middleware/.gitignore b/vendor/github.com/oapi-codegen/echo-middleware/.gitignore new file mode 100644 index 00000000..e660fd93 --- /dev/null +++ b/vendor/github.com/oapi-codegen/echo-middleware/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/vendor/github.com/oapi-codegen/echo-middleware/LICENSE b/vendor/github.com/oapi-codegen/echo-middleware/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/vendor/github.com/oapi-codegen/echo-middleware/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/oapi-codegen/echo-middleware/Makefile b/vendor/github.com/oapi-codegen/echo-middleware/Makefile new file mode 100644 index 00000000..91dd690e --- /dev/null +++ b/vendor/github.com/oapi-codegen/echo-middleware/Makefile @@ -0,0 +1,32 @@ +GOBASE=$(shell pwd) +GOBIN=$(GOBASE)/bin + +help: + @echo "This is a helper makefile for oapi-codegen" + @echo "Targets:" + @echo " generate: regenerate all generated files" + @echo " test: run all tests" + @echo " gin_example generate gin example server code" + @echo " tidy tidy go mod" + +$(GOBIN)/golangci-lint: + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.59.0 + +.PHONY: tools +tools: $(GOBIN)/golangci-lint + +lint: tools + $(GOBIN)/golangci-lint run ./... + +lint-ci: tools + $(GOBIN)/golangci-lint run ./... --out-format=github-actions --timeout=5m + +generate: + go generate ./... + +test: + go test -cover ./... + +tidy: + @echo "tidy..." + go mod tidy diff --git a/vendor/github.com/oapi-codegen/echo-middleware/README.md b/vendor/github.com/oapi-codegen/echo-middleware/README.md new file mode 100644 index 00000000..a2077ed3 --- /dev/null +++ b/vendor/github.com/oapi-codegen/echo-middleware/README.md @@ -0,0 +1,7 @@ +# Echo Middleware + +⚠️ This README may be for the latest development version, which may contain unreleased changes. Please ensure you're looking at the README for the latest release version. + +Middleware for the [Echo web server](https://github.com/labstack/echo) for use with [deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen). + +Licensed under the Apache-2.0. diff --git a/vendor/github.com/oapi-codegen/echo-middleware/oapi_validate.go b/vendor/github.com/oapi-codegen/echo-middleware/oapi_validate.go new file mode 100644 index 00000000..11dd1eb4 --- /dev/null +++ b/vendor/github.com/oapi-codegen/echo-middleware/oapi_validate.go @@ -0,0 +1,245 @@ +// Copyright 2019 DeepMap, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package echomiddleware + +import ( + "context" + "errors" + "fmt" + "log" + "net/http" + "os" + "strings" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/openapi3filter" + "github.com/getkin/kin-openapi/routers" + "github.com/getkin/kin-openapi/routers/gorillamux" + "github.com/labstack/echo/v4" + echomiddleware "github.com/labstack/echo/v4/middleware" +) + +const ( + EchoContextKey = "oapi-codegen/echo-context" + UserDataKey = "oapi-codegen/user-data" +) + +// OapiValidatorFromYamlFile is an Echo middleware function which validates incoming HTTP requests +// to make sure that they conform to the given OAPI 3.0 specification. When +// OAPI validation fails on the request, we return an HTTP/400. +// Create validator middleware from a YAML file path +func OapiValidatorFromYamlFile(path string) (echo.MiddlewareFunc, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("error reading %s: %w", path, err) + } + + swagger, err := openapi3.NewLoader().LoadFromData(data) + if err != nil { + return nil, fmt.Errorf("error parsing %s as Swagger YAML: %w", path, err) + } + return OapiRequestValidator(swagger), nil +} + +// OapiRequestValidator creates a validator from a swagger object. +func OapiRequestValidator(swagger *openapi3.T) echo.MiddlewareFunc { + return OapiRequestValidatorWithOptions(swagger, nil) +} + +// ErrorHandler is called when there is an error in validation +type ErrorHandler func(c echo.Context, err *echo.HTTPError) error + +// MultiErrorHandler is called when oapi returns a MultiError type +type MultiErrorHandler func(openapi3.MultiError) *echo.HTTPError + +// Options to customize request validation. These are passed through to +// openapi3filter. +type Options struct { + ErrorHandler ErrorHandler + Options openapi3filter.Options + ParamDecoder openapi3filter.ContentParameterDecoder + UserData interface{} + Skipper echomiddleware.Skipper + MultiErrorHandler MultiErrorHandler + // SilenceServersWarning allows silencing a warning for https://github.com/deepmap/oapi-codegen/issues/882 that reports when an OpenAPI spec has `spec.Servers != nil` + SilenceServersWarning bool +} + +// OapiRequestValidatorWithOptions creates a validator from a swagger object, with validation options +func OapiRequestValidatorWithOptions(swagger *openapi3.T, options *Options) echo.MiddlewareFunc { + if swagger.Servers != nil && (options == nil || !options.SilenceServersWarning) { + log.Println("WARN: OapiRequestValidatorWithOptions called with an OpenAPI spec that has `Servers` set. This may lead to an HTTP 400 with `no matching operation was found` when sending a valid request, as the validator performs `Host` header validation. If you're expecting `Host` header validation, you can silence this warning by setting `Options.SilenceServersWarning = true`. See https://github.com/deepmap/oapi-codegen/issues/882 for more information.") + } + + router, err := gorillamux.NewRouter(swagger) + if err != nil { + panic(err) + } + + skipper := getSkipperFromOptions(options) + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if skipper(c) { + return next(c) + } + + err := ValidateRequestFromContext(c, router, options) + if err != nil { + if options != nil && options.ErrorHandler != nil { + return options.ErrorHandler(c, err) + } + return err + } + return next(c) + } + } +} + +// ValidateRequestFromContext is called from the middleware above and actually does the work +// of validating a request. +func ValidateRequestFromContext(ctx echo.Context, router routers.Router, options *Options) *echo.HTTPError { + req := ctx.Request() + route, pathParams, err := router.FindRoute(req) + + // We failed to find a matching route for the request. + if err != nil { + switch e := err.(type) { + case *routers.RouteError: + // We've got a bad request, the path requested doesn't match + // either server, or path, or something. + return echo.NewHTTPError(http.StatusNotFound, e.Reason) + default: + // This should never happen today, but if our upstream code changes, + // we don't want to crash the server, so handle the unexpected error. + return echo.NewHTTPError(http.StatusInternalServerError, + fmt.Sprintf("error validating route: %s", err.Error())) + } + } + + validationInput := &openapi3filter.RequestValidationInput{ + Request: req, + PathParams: pathParams, + Route: route, + } + + // Pass the Echo context into the request validator, so that any callbacks + // which it invokes make it available. + requestContext := context.WithValue(context.Background(), EchoContextKey, ctx) //nolint:staticcheck + + if options != nil { + validationInput.Options = &options.Options + validationInput.ParamDecoder = options.ParamDecoder + requestContext = context.WithValue(requestContext, UserDataKey, options.UserData) //nolint:staticcheck + } + + err = openapi3filter.ValidateRequest(requestContext, validationInput) + if err != nil { + me := openapi3.MultiError{} + if errors.As(err, &me) { + errFunc := getMultiErrorHandlerFromOptions(options) + return errFunc(me) + } + + switch e := err.(type) { + case *openapi3filter.RequestError: + // We've got a bad request + // Split up the verbose error by lines and return the first one + // openapi errors seem to be multi-line with a decent message on the first + errorLines := strings.Split(e.Error(), "\n") + return &echo.HTTPError{ + Code: http.StatusBadRequest, + Message: errorLines[0], + Internal: err, + } + case *openapi3filter.SecurityRequirementsError: + for _, err := range e.Errors { + httpErr, ok := err.(*echo.HTTPError) + if ok { + return httpErr + } + } + return &echo.HTTPError{ + Code: http.StatusForbidden, + Message: e.Error(), + Internal: err, + } + default: + // This should never happen today, but if our upstream code changes, + // we don't want to crash the server, so handle the unexpected error. + return &echo.HTTPError{ + Code: http.StatusInternalServerError, + Message: fmt.Sprintf("error validating request: %s", err), + Internal: err, + } + } + } + return nil +} + +// GetEchoContext gets the echo context from within requests. It returns +// nil if not found or wrong type. +func GetEchoContext(c context.Context) echo.Context { + iface := c.Value(EchoContextKey) + if iface == nil { + return nil + } + eCtx, ok := iface.(echo.Context) + if !ok { + return nil + } + return eCtx +} + +func GetUserData(c context.Context) interface{} { + return c.Value(UserDataKey) +} + +// attempt to get the skipper from the options whether it is set or not +func getSkipperFromOptions(options *Options) echomiddleware.Skipper { + if options == nil { + return echomiddleware.DefaultSkipper + } + + if options.Skipper == nil { + return echomiddleware.DefaultSkipper + } + + return options.Skipper +} + +// attempt to get the MultiErrorHandler from the options. If it is not set, +// return a default handler +func getMultiErrorHandlerFromOptions(options *Options) MultiErrorHandler { + if options == nil { + return defaultMultiErrorHandler + } + + if options.MultiErrorHandler == nil { + return defaultMultiErrorHandler + } + + return options.MultiErrorHandler +} + +// defaultMultiErrorHandler returns a StatusBadRequest (400) and a list +// of all of the errors. This method is called if there are no other +// methods defined on the options. +func defaultMultiErrorHandler(me openapi3.MultiError) *echo.HTTPError { + return &echo.HTTPError{ + Code: http.StatusBadRequest, + Message: me.Error(), + Internal: me, + } +} diff --git a/vendor/github.com/oapi-codegen/echo-middleware/renovate.json b/vendor/github.com/oapi-codegen/echo-middleware/renovate.json new file mode 100644 index 00000000..c4e1abbd --- /dev/null +++ b/vendor/github.com/oapi-codegen/echo-middleware/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "local>oapi-codegen/renovate-config" + ] +} diff --git a/vendor/github.com/oapi-codegen/echo-middleware/test_spec.yaml b/vendor/github.com/oapi-codegen/echo-middleware/test_spec.yaml new file mode 100644 index 00000000..1f847d75 --- /dev/null +++ b/vendor/github.com/oapi-codegen/echo-middleware/test_spec.yaml @@ -0,0 +1,103 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: TestServer +servers: + - url: http://deepmap.ai +paths: + /resource: + get: + operationId: getResource + parameters: + - name: id + in: query + schema: + type: integer + minimum: 10 + maximum: 100 + responses: + '200': + description: success + content: + application/json: + schema: + properties: + name: + type: string + id: + type: integer + post: + operationId: createResource + responses: + '204': + description: No content + requestBody: + required: true + content: + application/json: + schema: + properties: + name: + type: string + /protected_resource: + get: + operationId: getProtectedResource + security: + - BearerAuth: + - someScope + responses: + '204': + description: no content + /protected_resource2: + get: + operationId: getProtectedResource + security: + - BearerAuth: + - otherScope + responses: + '204': + description: no content + /protected_resource_401: + get: + operationId: getProtectedResource + security: + - BearerAuth: + - unauthorized + responses: + '401': + description: no content + /multiparamresource: + get: + operationId: getResource + parameters: + - name: id + in: query + required: true + schema: + type: integer + minimum: 10 + maximum: 100 + - name: id2 + required: true + in: query + schema: + type: integer + minimum: 10 + maximum: 100 + responses: + '200': + description: success + content: + application/json: + schema: + properties: + name: + type: string + id: + type: integer +components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT diff --git a/vendor/modules.txt b/vendor/modules.txt index c2ef9c06..59d9a069 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -235,6 +235,11 @@ github.com/gabriel-vasile/mimetype/internal/magic # github.com/getkin/kin-openapi v0.129.0 ## explicit; go 1.22.5 github.com/getkin/kin-openapi/openapi3 +github.com/getkin/kin-openapi/openapi3filter +github.com/getkin/kin-openapi/routers +github.com/getkin/kin-openapi/routers/gorillamux +github.com/getkin/kin-openapi/routers/legacy +github.com/getkin/kin-openapi/routers/legacy/pathpattern # github.com/ghodss/yaml v1.0.0 ## explicit github.com/ghodss/yaml @@ -291,6 +296,9 @@ github.com/golang-migrate/migrate/v4/source/iofs # github.com/google/uuid v1.6.0 ## explicit github.com/google/uuid +# github.com/gorilla/mux v1.8.1 +## explicit; go 1.20 +github.com/gorilla/mux # github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 ## explicit; go 1.23.0 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule @@ -444,6 +452,9 @@ github.com/morikuni/aec # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 ## explicit github.com/munnerz/goautoneg +# github.com/oapi-codegen/echo-middleware v1.0.2 +## explicit; go 1.20 +github.com/oapi-codegen/echo-middleware # github.com/oapi-codegen/runtime v1.1.1 ## explicit; go 1.20 github.com/oapi-codegen/runtime