From a58f4d884db053df4b941ba02029e2f28a62e081 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 11:53:44 +1000 Subject: [PATCH 01/42] Add generic middleware implementation --- nitric/middleware.go | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 nitric/middleware.go diff --git a/nitric/middleware.go b/nitric/middleware.go new file mode 100644 index 0000000..72b5e82 --- /dev/null +++ b/nitric/middleware.go @@ -0,0 +1,59 @@ +package nitric + +import "fmt" + +type Handler[T any] func(context *T) (*T, error) +type Middleware[T any] func(context *T, next Handler[T]) (*T, error) + +type chainedMiddleware[T any] struct { + fun Middleware[T] + nextFunc Handler[T] +} + +func (c *chainedMiddleware[T]) invoke(ctx *T) (*T, error) { + // Chains are left open-ended so middleware can continue to be linked + // If the chain is incomplete, set a chained dummy handler for safety + if c.nextFunc == nil { + c.nextFunc = func(ctx *T) (*T, error) { + return ctx, nil + } + } + + return c.fun(ctx, c.nextFunc) +} + +type middlewareChain[T any] struct { + chain []*chainedMiddleware[T] +} + +func (h *middlewareChain[T]) invoke(ctx *T, next Handler[T]) (*T, error) { + if len(h.chain) == 0 { + return nil, fmt.Errorf("there are no middleware in this chain") + } + // Complete the chain + h.chain[len(h.chain)-1].nextFunc = next + + return h.chain[0].invoke(ctx) +} + +func Compose[T any](funcs ...Middleware[T]) Middleware[T] { + mwareChain := &middlewareChain[T]{ + chain: make([]*chainedMiddleware[T], len(funcs)), + } + + var nextFunc Handler[T] = nil + for i := len(funcs) - 1; i >= 0; i = i - 1 { + if funcs[i] == nil { + fmt.Println("this func is empty") + } + + cm := &chainedMiddleware[T]{ + fun: funcs[i], + nextFunc: nextFunc, + } + nextFunc = cm.invoke + mwareChain.chain[i] = cm + } + + return mwareChain.invoke +} From 1cfc16db68df33760595f24e3443df79121c4785 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 11:58:18 +1000 Subject: [PATCH 02/42] cleanup --- nitric/middleware.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/nitric/middleware.go b/nitric/middleware.go index 72b5e82..a4a50ad 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -10,13 +10,15 @@ type chainedMiddleware[T any] struct { nextFunc Handler[T] } +func DummyHandler[T any](ctx *T) (*T, error) { + return ctx, nil +} + func (c *chainedMiddleware[T]) invoke(ctx *T) (*T, error) { // Chains are left open-ended so middleware can continue to be linked // If the chain is incomplete, set a chained dummy handler for safety if c.nextFunc == nil { - c.nextFunc = func(ctx *T) (*T, error) { - return ctx, nil - } + c.nextFunc = DummyHandler[T] } return c.fun(ctx, c.nextFunc) @@ -36,15 +38,16 @@ func (h *middlewareChain[T]) invoke(ctx *T, next Handler[T]) (*T, error) { return h.chain[0].invoke(ctx) } +// Compose - Takes a collection of middleware and composes it into a single middleware function func Compose[T any](funcs ...Middleware[T]) Middleware[T] { mwareChain := &middlewareChain[T]{ - chain: make([]*chainedMiddleware[T], len(funcs)), + chain: []*chainedMiddleware[T]{}, } var nextFunc Handler[T] = nil for i := len(funcs) - 1; i >= 0; i = i - 1 { if funcs[i] == nil { - fmt.Println("this func is empty") + continue } cm := &chainedMiddleware[T]{ @@ -52,7 +55,7 @@ func Compose[T any](funcs ...Middleware[T]) Middleware[T] { nextFunc: nextFunc, } nextFunc = cm.invoke - mwareChain.chain[i] = cm + mwareChain.chain = append(mwareChain.chain, cm) } return mwareChain.invoke From f5823119972a3fd952e2d0554398a10474d4014f Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 13:53:55 +1000 Subject: [PATCH 03/42] large refactor not a true refactor as there are breaking changes. --- api/http/context.go | 71 +++++ api/http/request.go | 43 +++ api/http/response.go | 7 + api/schedules/context.go | 37 +++ api/schedules/request.go | 13 + api/schedules/response.go | 5 + api/storage/context.go | 47 +++ api/storage/request.go | 48 +++ api/storage/response.go | 9 + api/topics/context.go | 40 +++ api/topics/request.go | 19 ++ api/topics/response.go | 5 + api/websockets/context.go | 73 +++++ api/websockets/request.go | 57 ++++ api/websockets/response.go | 5 + handler/blob_event.go | 68 ----- handler/context.go | 276 ------------------ handler/file_event.go | 68 ----- handler/http.go | 79 ----- handler/interval.go | 68 ----- handler/message.go | 68 ----- handler/request.go | 201 ------------- handler/response.go | 41 --- handler/websocket.go | 68 ----- nitric/api.go | 85 +++--- workers/api.go => nitric/api_workers.go | 26 +- nitric/bucket.go | 16 +- .../blob_event.go => nitric/bucket_workers.go | 24 +- nitric/manager.go | 11 +- nitric/middleware.go | 4 +- nitric/options.go | 8 +- nitric/schedule.go | 23 +- .../interval.go => nitric/schedule_workers.go | 24 +- nitric/topic.go | 12 +- .../topic_workers.go | 24 +- nitric/websocket.go | 18 +- .../websocket_workers.go | 24 +- {workers => nitric}/workers.go | 4 +- tools/tools.go | 3 + 39 files changed, 625 insertions(+), 1097 deletions(-) create mode 100644 api/http/context.go create mode 100644 api/http/request.go create mode 100644 api/http/response.go create mode 100644 api/schedules/context.go create mode 100644 api/schedules/request.go create mode 100644 api/schedules/response.go create mode 100644 api/storage/context.go create mode 100644 api/storage/request.go create mode 100644 api/storage/response.go create mode 100644 api/topics/context.go create mode 100644 api/topics/request.go create mode 100644 api/topics/response.go create mode 100644 api/websockets/context.go create mode 100644 api/websockets/request.go create mode 100644 api/websockets/response.go delete mode 100644 handler/blob_event.go delete mode 100644 handler/context.go delete mode 100644 handler/file_event.go delete mode 100644 handler/http.go delete mode 100644 handler/interval.go delete mode 100644 handler/message.go delete mode 100644 handler/request.go delete mode 100644 handler/response.go delete mode 100644 handler/websocket.go rename workers/api.go => nitric/api_workers.go (82%) rename workers/blob_event.go => nitric/bucket_workers.go (82%) rename workers/interval.go => nitric/schedule_workers.go (82%) rename workers/subscription.go => nitric/topic_workers.go (82%) rename workers/websocket.go => nitric/websocket_workers.go (82%) rename {workers => nitric}/workers.go (93%) diff --git a/api/http/context.go b/api/http/context.go new file mode 100644 index 0000000..a37f2cd --- /dev/null +++ b/api/http/context.go @@ -0,0 +1,71 @@ +package http + +import apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" + +type Ctx struct { + id string + Request Request + Response *Response + Extras map[string]interface{} +} + +func (c *Ctx) ToClientMessage() *apispb.ClientMessage { + headers := make(map[string]*apispb.HeaderValue) + for k, v := range c.Response.Headers { + headers[k] = &apispb.HeaderValue{ + Value: v, + } + } + + return &apispb.ClientMessage{ + Id: c.id, + Content: &apispb.ClientMessage_HttpResponse{ + HttpResponse: &apispb.HttpResponse{ + Status: int32(c.Response.Status), + Headers: headers, + Body: c.Response.Body, + }, + }, + } +} + +func NewCtx(msg *apispb.ServerMessage) *Ctx { + req := msg.GetHttpRequest() + + headers := make(map[string][]string) + for k, v := range req.Headers { + headers[k] = v.GetValue() + } + + query := make(map[string][]string) + for k, v := range req.QueryParams { + query[k] = v.GetValue() + } + + return &Ctx{ + id: msg.Id, + Request: &RequestImpl{ + method: req.Method, + path: req.Path, + pathParams: req.PathParams, + query: query, + headers: headers, + data: req.Body, + }, + Response: &Response{ + Status: 200, + Headers: map[string][]string{}, + Body: nil, + }, + } +} + +func (c *Ctx) WithError(err error) { + c.Response = &Response{ + Status: 500, + Headers: map[string][]string{ + "Content-Type": {"text/plain"}, + }, + Body: []byte("Internal Server Error"), + } +} diff --git a/api/http/request.go b/api/http/request.go new file mode 100644 index 0000000..83b044b --- /dev/null +++ b/api/http/request.go @@ -0,0 +1,43 @@ +package http + +type Request interface { + Method() string + Path() string + Data() []byte + Query() map[string][]string + Headers() map[string][]string + PathParams() map[string]string +} + +type RequestImpl struct { + method string + path string + data []byte + query map[string][]string + headers map[string][]string + pathParams map[string]string +} + +func (h *RequestImpl) Method() string { + return h.method +} + +func (h *RequestImpl) Path() string { + return h.path +} + +func (h *RequestImpl) Data() []byte { + return h.data +} + +func (h *RequestImpl) Query() map[string][]string { + return h.query +} + +func (h *RequestImpl) Headers() map[string][]string { + return h.headers +} + +func (h *RequestImpl) PathParams() map[string]string { + return h.pathParams +} diff --git a/api/http/response.go b/api/http/response.go new file mode 100644 index 0000000..62a4849 --- /dev/null +++ b/api/http/response.go @@ -0,0 +1,7 @@ +package http + +type Response struct { + Status int + Headers map[string][]string + Body []byte +} diff --git a/api/schedules/context.go b/api/schedules/context.go new file mode 100644 index 0000000..f1d165a --- /dev/null +++ b/api/schedules/context.go @@ -0,0 +1,37 @@ +package schedules + +import schedulespb "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" + +type Ctx struct { + id string + Request Request + Response *Response + Extras map[string]interface{} +} + +func (c *Ctx) ToClientMessage() *schedulespb.ClientMessage { + return &schedulespb.ClientMessage{ + Id: c.id, + Content: &schedulespb.ClientMessage_IntervalResponse{ + IntervalResponse: &schedulespb.IntervalResponse{}, + }, + } +} + +func NewCtx(msg *schedulespb.ServerMessage) *Ctx { + return &Ctx{ + id: msg.Id, + Request: &requestImpl{ + scheduleName: msg.GetIntervalRequest().ScheduleName, + }, + Response: &Response{ + Success: true, + }, + } +} + +func (c *Ctx) WithError(err error) { + c.Response = &Response{ + Success: false, + } +} diff --git a/api/schedules/request.go b/api/schedules/request.go new file mode 100644 index 0000000..3b95313 --- /dev/null +++ b/api/schedules/request.go @@ -0,0 +1,13 @@ +package schedules + +type Request interface { + ScheduleName() string +} + +type requestImpl struct { + scheduleName string +} + +func (i *requestImpl) ScheduleName() string { + return i.scheduleName +} diff --git a/api/schedules/response.go b/api/schedules/response.go new file mode 100644 index 0000000..a46caec --- /dev/null +++ b/api/schedules/response.go @@ -0,0 +1,5 @@ +package schedules + +type Response struct { + Success bool +} diff --git a/api/storage/context.go b/api/storage/context.go new file mode 100644 index 0000000..ea3c1a9 --- /dev/null +++ b/api/storage/context.go @@ -0,0 +1,47 @@ +package storage + +import storagepb "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" + +type Ctx struct { + id string + Request Request + Response *Response + Extras map[string]interface{} +} + +func (c *Ctx) ToClientMessage() *storagepb.ClientMessage { + return &storagepb.ClientMessage{ + Id: c.id, + Content: &storagepb.ClientMessage_BlobEventResponse{ + BlobEventResponse: &storagepb.BlobEventResponse{ + Success: c.Response.Success, + }, + }, + } +} + +func NewCtx(msg *storagepb.ServerMessage) *Ctx { + req := msg.GetBlobEventRequest() + + return &Ctx{ + id: msg.Id, + Request: &requestImpl{ + key: req.GetBlobEvent().Key, + }, + Response: &Response{ + Success: true, + }, + } +} + +func (c *Ctx) WithError(err error) { + c.Response = &Response{ + Success: false, + } +} + +type FileCtx struct { + Request FileRequest + Response *FileResponse + Extras map[string]interface{} +} diff --git a/api/storage/request.go b/api/storage/request.go new file mode 100644 index 0000000..e8b10ab --- /dev/null +++ b/api/storage/request.go @@ -0,0 +1,48 @@ +package storage + +type EventType string + +var EventTypes = []EventType{WriteNotification, DeleteNotification} + +const ( + WriteNotification EventType = "write" + DeleteNotification EventType = "delete" +) + +type Request interface { + Key() string + NotificationType() EventType +} + +type requestImpl struct { + key string + notificationType EventType +} + +func (b *requestImpl) Key() string { + return b.key +} + +func (b *requestImpl) NotificationType() EventType { + return b.notificationType +} + +// File Event + +type FileRequest interface { + Bucket() *Bucket + NotificationType() EventType +} + +type fileRequestImpl struct { + bucket Bucket + notificationType EventType +} + +func (f *fileRequestImpl) Bucket() Bucket { + return f.bucket +} + +func (f *fileRequestImpl) NotificationType() EventType { + return f.notificationType +} diff --git a/api/storage/response.go b/api/storage/response.go new file mode 100644 index 0000000..7e92d5a --- /dev/null +++ b/api/storage/response.go @@ -0,0 +1,9 @@ +package storage + +type Response struct { + Success bool +} + +type FileResponse struct { + Success bool +} diff --git a/api/topics/context.go b/api/topics/context.go new file mode 100644 index 0000000..548db10 --- /dev/null +++ b/api/topics/context.go @@ -0,0 +1,40 @@ +package topics + +import topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" + +type Ctx struct { + id string + Request Request + Response *Response + Extras map[string]interface{} +} + +func (c *Ctx) ToClientMessage() *topicspb.ClientMessage { + return &topicspb.ClientMessage{ + Id: c.id, + Content: &topicspb.ClientMessage_MessageResponse{ + MessageResponse: &topicspb.MessageResponse{ + Success: true, + }, + }, + } +} + +func NewCtx(msg *topicspb.ServerMessage) *Ctx { + return &Ctx{ + id: msg.Id, + Request: &requestImpl{ + topicName: msg.GetMessageRequest().TopicName, + message: msg.GetMessageRequest().Message.GetStructPayload().AsMap(), + }, + Response: &Response{ + Success: true, + }, + } +} + +func (c *Ctx) WithError(err error) { + c.Response = &Response{ + Success: false, + } +} diff --git a/api/topics/request.go b/api/topics/request.go new file mode 100644 index 0000000..26735e7 --- /dev/null +++ b/api/topics/request.go @@ -0,0 +1,19 @@ +package topics + +type Request interface { + TopicName() string + Message() map[string]interface{} +} + +type requestImpl struct { + topicName string + message map[string]interface{} +} + +func (m *requestImpl) TopicName() string { + return m.topicName +} + +func (m *requestImpl) Message() map[string]interface{} { + return m.message +} diff --git a/api/topics/response.go b/api/topics/response.go new file mode 100644 index 0000000..338023c --- /dev/null +++ b/api/topics/response.go @@ -0,0 +1,5 @@ +package topics + +type Response struct { + Success bool +} diff --git a/api/websockets/context.go b/api/websockets/context.go new file mode 100644 index 0000000..5f44062 --- /dev/null +++ b/api/websockets/context.go @@ -0,0 +1,73 @@ +package websockets + +import websocketspb "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" + +type Ctx struct { + id string + Request Request + Response *Response + Extras map[string]interface{} +} + +func (c *Ctx) ToClientMessage() *websocketspb.ClientMessage { + return &websocketspb.ClientMessage{ + Id: c.id, + Content: &websocketspb.ClientMessage_WebsocketEventResponse{ + WebsocketEventResponse: &websocketspb.WebsocketEventResponse{ + WebsocketResponse: &websocketspb.WebsocketEventResponse_ConnectionResponse{ + ConnectionResponse: &websocketspb.WebsocketConnectionResponse{ + Reject: c.Response.Reject, + }, + }, + }, + }, + } +} + +func NewCtx(msg *websocketspb.ServerMessage) *Ctx { + req := msg.GetWebsocketEventRequest() + + var eventType EventType + switch req.WebsocketEvent.(type) { + case *websocketspb.WebsocketEventRequest_Disconnection: + eventType = EventType_Disconnect + case *websocketspb.WebsocketEventRequest_Message: + eventType = EventType_Message + default: + eventType = EventType_Connect + } + + queryParams := make(map[string]*websocketspb.QueryValue) + if eventType == EventType_Connect { + for key, value := range req.GetConnection().GetQueryParams() { + queryParams[key] = &websocketspb.QueryValue{ + Value: value.Value, + } + } + } + + var _message string = "" + if req.GetMessage() != nil { + _message = string(req.GetMessage().Body) + } + + return &Ctx{ + id: msg.Id, + Request: &requestImpl{ + socketName: req.SocketName, + eventType: eventType, + connectionId: req.ConnectionId, + queryParams: queryParams, + message: _message, + }, + Response: &Response{ + Reject: false, + }, + } +} + +func (c *Ctx) WithError(err error) { + c.Response = &Response{ + Reject: true, + } +} diff --git a/api/websockets/request.go b/api/websockets/request.go new file mode 100644 index 0000000..a303c0e --- /dev/null +++ b/api/websockets/request.go @@ -0,0 +1,57 @@ +package websockets + +import ( + websocketspb "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" +) + +type EventType string + +var EventTypes = []EventType{EventType_Connect, EventType_Disconnect, EventType_Message} + +const ( + EventType_Connect EventType = "connect" + EventType_Disconnect EventType = "disconnect" + EventType_Message EventType = "message" +) + +type Request interface { + SocketName() string + EventType() EventType + ConnectionID() string + QueryParams() map[string][]string + Message() string +} + +type requestImpl struct { + socketName string + eventType EventType + connectionId string + queryParams map[string]*websocketspb.QueryValue + message string +} + +func (w *requestImpl) SocketName() string { + return w.socketName +} + +func (w *requestImpl) EventType() EventType { + return w.eventType +} + +func (w *requestImpl) ConnectionID() string { + return w.connectionId +} + +func (w *requestImpl) QueryParams() map[string][]string { + queryParams := map[string][]string{} + + for k, v := range w.queryParams { + queryParams[k] = v.Value + } + + return queryParams +} + +func (w *requestImpl) Message() string { + return w.message +} diff --git a/api/websockets/response.go b/api/websockets/response.go new file mode 100644 index 0000000..7150d3b --- /dev/null +++ b/api/websockets/response.go @@ -0,0 +1,5 @@ +package websockets + +type Response struct { + Reject bool +} diff --git a/handler/blob_event.go b/handler/blob_event.go deleted file mode 100644 index 497bb33..0000000 --- a/handler/blob_event.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -type ( - BlobEventHandler = func(*BlobEventContext) (*BlobEventContext, error) - BlobEventMiddleware = func(*BlobEventContext, BlobEventHandler) (*BlobEventContext, error) -) - -func BlobEventDummy(ctx *BlobEventContext) (*BlobEventContext, error) { - return ctx, nil -} - -type chainedBlobEventMiddleware struct { - fun BlobEventMiddleware - nextFunc BlobEventHandler -} - -// automatically finalize chain with dummy function -func (c *chainedBlobEventMiddleware) invoke(ctx *BlobEventContext) (*BlobEventContext, error) { - if c.nextFunc == nil { - c.nextFunc = BlobEventDummy - } - - return c.fun(ctx, c.nextFunc) -} - -type blobEventMiddlewareChain struct { - chain []*chainedBlobEventMiddleware -} - -func (h *blobEventMiddlewareChain) invoke(ctx *BlobEventContext, next BlobEventHandler) (*BlobEventContext, error) { - // Complete the chain - h.chain[len(h.chain)-1].nextFunc = next - - return h.chain[0].invoke(ctx) -} - -// ComposeEventMiddleware - Composes an array of middleware into a single middleware -func ComposeBlobEventMiddleware(funcs ...BlobEventMiddleware) BlobEventMiddleware { - mwareChain := &blobEventMiddlewareChain{ - chain: make([]*chainedBlobEventMiddleware, len(funcs)), - } - - var nextFunc BlobEventHandler = nil - for i := len(funcs) - 1; i >= 0; i = i - 1 { - cm := &chainedBlobEventMiddleware{ - fun: funcs[i], - nextFunc: nextFunc, - } - nextFunc = cm.invoke - mwareChain.chain[i] = cm - } - - return mwareChain.invoke -} diff --git a/handler/context.go b/handler/context.go deleted file mode 100644 index ba56501..0000000 --- a/handler/context.go +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -import ( - http "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" - schedules "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" - storage "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" - topics "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" - websockets "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" -) - -type HttpContext struct { - id string - Request HttpRequest - Response *HttpResponse - Extras map[string]interface{} -} - -func (c *HttpContext) ToClientMessage() *http.ClientMessage { - headers := make(map[string]*http.HeaderValue) - for k, v := range c.Response.Headers { - headers[k] = &http.HeaderValue{ - Value: v, - } - } - - return &http.ClientMessage{ - Id: c.id, - Content: &http.ClientMessage_HttpResponse{ - HttpResponse: &http.HttpResponse{ - Status: int32(c.Response.Status), - Headers: headers, - Body: c.Response.Body, - }, - }, - } -} - -func NewHttpContext(msg *http.ServerMessage) *HttpContext { - req := msg.GetHttpRequest() - - headers := make(map[string][]string) - for k, v := range req.Headers { - headers[k] = v.GetValue() - } - - query := make(map[string][]string) - for k, v := range req.QueryParams { - query[k] = v.GetValue() - } - - return &HttpContext{ - id: msg.Id, - Request: &httpRequestImpl{ - method: req.Method, - path: req.Path, - pathParams: req.PathParams, - query: query, - headers: headers, - data: req.Body, - }, - Response: &HttpResponse{ - Status: 200, - Headers: map[string][]string{}, - Body: nil, - }, - } -} - -func (c *HttpContext) WithError(err error) { - c.Response = &HttpResponse{ - Status: 500, - Headers: map[string][]string{ - "Content-Type": {"text/plain"}, - }, - Body: []byte("Internal Server Error"), - } -} - -type MessageContext struct { - id string - Request MessageRequest - Response *MessageResponse - Extras map[string]interface{} -} - -func (c *MessageContext) ToClientMessage() *topics.ClientMessage { - return &topics.ClientMessage{ - Id: c.id, - Content: &topics.ClientMessage_MessageResponse{ - MessageResponse: &topics.MessageResponse{ - Success: true, - }, - }, - } -} - -func NewMessageContext(msg *topics.ServerMessage) *MessageContext { - return &MessageContext{ - id: msg.Id, - Request: &messageRequestImpl{ - topicName: msg.GetMessageRequest().TopicName, - message: msg.GetMessageRequest().Message.GetStructPayload().AsMap(), - }, - Response: &MessageResponse{ - Success: true, - }, - } -} - -func (c *MessageContext) WithError(err error) { - c.Response = &MessageResponse{ - Success: false, - } -} - -type IntervalContext struct { - id string - Request IntervalRequest - Response *IntervalResponse - Extras map[string]interface{} -} - -func (c *IntervalContext) ToClientMessage() *schedules.ClientMessage { - return &schedules.ClientMessage{ - Id: c.id, - Content: &schedules.ClientMessage_IntervalResponse{ - IntervalResponse: &schedules.IntervalResponse{}, - }, - } -} - -func NewIntervalContext(msg *schedules.ServerMessage) *IntervalContext { - return &IntervalContext{ - id: msg.Id, - Request: &intervalRequestImpl{ - scheduleName: msg.GetIntervalRequest().ScheduleName, - }, - Response: &IntervalResponse{ - Success: true, - }, - } -} - -func (c *IntervalContext) WithError(err error) { - c.Response = &IntervalResponse{ - Success: false, - } -} - -type BlobEventContext struct { - id string - Request BlobEventRequest - Response *BlobEventResponse - Extras map[string]interface{} -} - -func (c *BlobEventContext) ToClientMessage() *storage.ClientMessage { - return &storage.ClientMessage{ - Id: c.id, - Content: &storage.ClientMessage_BlobEventResponse{ - BlobEventResponse: &storage.BlobEventResponse{ - Success: c.Response.Success, - }, - }, - } -} - -func NewBlobEventContext(msg *storage.ServerMessage) *BlobEventContext { - req := msg.GetBlobEventRequest() - - return &BlobEventContext{ - id: msg.Id, - Request: &blobEventRequestImpl{ - key: req.GetBlobEvent().Key, - }, - Response: &BlobEventResponse{ - Success: true, - }, - } -} - -func (c *BlobEventContext) WithError(err error) { - c.Response = &BlobEventResponse{ - Success: false, - } -} - -type FileEventContext struct { - Request FileEventRequest - Response *FileEventResponse - Extras map[string]interface{} -} - -type WebsocketContext struct { - id string - Request WebsocketRequest - Response *WebsocketResponse - Extras map[string]interface{} -} - -func (c *WebsocketContext) ToClientMessage() *websockets.ClientMessage { - return &websockets.ClientMessage{ - Id: c.id, - Content: &websockets.ClientMessage_WebsocketEventResponse{ - WebsocketEventResponse: &websockets.WebsocketEventResponse{ - WebsocketResponse: &websockets.WebsocketEventResponse_ConnectionResponse{ - ConnectionResponse: &websockets.WebsocketConnectionResponse{ - Reject: c.Response.Reject, - }, - }, - }, - }, - } -} - -func NewWebsocketContext(msg *websockets.ServerMessage) *WebsocketContext { - req := msg.GetWebsocketEventRequest() - - var eventType WebsocketEventType - switch req.WebsocketEvent.(type) { - case *websockets.WebsocketEventRequest_Disconnection: - eventType = WebsocketDisconnect - case *websockets.WebsocketEventRequest_Message: - eventType = WebsocketMessage - default: - eventType = WebsocketConnect - } - - queryParams := make(map[string]*http.QueryValue) - if eventType == WebsocketConnect { - for key, value := range req.GetConnection().GetQueryParams() { - queryParams[key] = &http.QueryValue{ - Value: value.Value, - } - } - } - - var _message string = "" - if req.GetMessage() != nil { - _message = string(req.GetMessage().Body) - } - - return &WebsocketContext{ - id: msg.Id, - Request: &websocketRequestImpl{ - socketName: req.SocketName, - eventType: eventType, - connectionId: req.ConnectionId, - queryParams: queryParams, - message: _message, - }, - Response: &WebsocketResponse{ - Reject: false, - }, - } -} - -func (c *WebsocketContext) WithError(err error) { - c.Response = &WebsocketResponse{ - Reject: true, - } -} diff --git a/handler/file_event.go b/handler/file_event.go deleted file mode 100644 index bfa5caf..0000000 --- a/handler/file_event.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -type ( - FileEventHandler = func(*FileEventContext) (*FileEventContext, error) - FileEventMiddleware = func(*FileEventContext, FileEventHandler) (*FileEventContext, error) -) - -func fileEventDummy(ctx *FileEventContext) (*FileEventContext, error) { - return ctx, nil -} - -type chainedFileEventMiddleware struct { - fun FileEventMiddleware - nextFunc FileEventHandler -} - -// automatically finalize chain with dummy function -func (c *chainedFileEventMiddleware) invoke(ctx *FileEventContext) (*FileEventContext, error) { - if c.nextFunc == nil { - c.nextFunc = fileEventDummy - } - - return c.fun(ctx, c.nextFunc) -} - -type fileEventMiddlewareChain struct { - chain []*chainedFileEventMiddleware -} - -func (h *fileEventMiddlewareChain) invoke(ctx *FileEventContext, next FileEventHandler) (*FileEventContext, error) { - // Complete the chain - h.chain[len(h.chain)-1].nextFunc = next - - return h.chain[0].invoke(ctx) -} - -// ComposeEventMiddleware - Composes an array of middleware into a single middleware -func ComposeFileEventMiddleware(funcs ...FileEventMiddleware) FileEventMiddleware { - mwareChain := &fileEventMiddlewareChain{ - chain: make([]*chainedFileEventMiddleware, len(funcs)), - } - - var nextFunc FileEventHandler = nil - for i := len(funcs) - 1; i >= 0; i = i - 1 { - cm := &chainedFileEventMiddleware{ - fun: funcs[i], - nextFunc: nextFunc, - } - nextFunc = cm.invoke - mwareChain.chain[i] = cm - } - - return mwareChain.invoke -} diff --git a/handler/http.go b/handler/http.go deleted file mode 100644 index bfef1d1..0000000 --- a/handler/http.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -import "fmt" - -type ( - HttpHandler = func(*HttpContext) (*HttpContext, error) - HttpMiddleware = func(*HttpContext, HttpHandler) (*HttpContext, error) -) - -func HttpDummy(ctx *HttpContext) (*HttpContext, error) { - return ctx, nil -} - -type chainedHttpMiddleware struct { - fun HttpMiddleware - nextFunc HttpHandler -} - -// automatically finalize chain with dummy function -func (c *chainedHttpMiddleware) invoke(ctx *HttpContext) (*HttpContext, error) { - // Chains are left open-ended so middleware can continue to be linked - // If the chain is incomplete, set a chained dummy handler for safety - if c.nextFunc == nil { - c.nextFunc = HttpDummy - } - - return c.fun(ctx, c.nextFunc) -} - -type httpMiddlewareChain struct { - chain []*chainedHttpMiddleware -} - -func (h *httpMiddlewareChain) invoke(ctx *HttpContext, next HttpHandler) (*HttpContext, error) { - if len(h.chain) == 0 { - return nil, fmt.Errorf("there are no middleware in this chain") - } - // Complete the chain - h.chain[len(h.chain)-1].nextFunc = next - - return h.chain[0].invoke(ctx) -} - -// ComposeHttpMiddleware - Composes an array of middleware into a single middleware -func ComposeHttpMiddleware(funcs ...HttpMiddleware) HttpMiddleware { - mwareChain := &httpMiddlewareChain{ - chain: make([]*chainedHttpMiddleware, len(funcs)), - } - - var nextFunc HttpHandler = nil - for i := len(funcs) - 1; i >= 0; i = i - 1 { - if funcs[i] == nil { - fmt.Println("this func is empty") - } - - cm := &chainedHttpMiddleware{ - fun: funcs[i], - nextFunc: nextFunc, - } - nextFunc = cm.invoke - mwareChain.chain[i] = cm - } - - return mwareChain.invoke -} diff --git a/handler/interval.go b/handler/interval.go deleted file mode 100644 index 4d37cd4..0000000 --- a/handler/interval.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -type ( - IntervalHandler = func(*IntervalContext) (*IntervalContext, error) - IntervalMiddleware = func(*IntervalContext, IntervalHandler) (*IntervalContext, error) -) - -func IntervalDummy(ctx *IntervalContext) (*IntervalContext, error) { - return ctx, nil -} - -type chainedIntervalMiddleware struct { - fun IntervalMiddleware - nextFunc IntervalHandler -} - -// automatically finalize chain with dummy function -func (c *chainedIntervalMiddleware) invoke(ctx *IntervalContext) (*IntervalContext, error) { - if c.nextFunc == nil { - c.nextFunc = IntervalDummy - } - - return c.fun(ctx, c.nextFunc) -} - -type intervalMiddlewareChain struct { - chain []*chainedIntervalMiddleware -} - -func (h *intervalMiddlewareChain) invoke(ctx *IntervalContext, next IntervalHandler) (*IntervalContext, error) { - // Complete the chain - h.chain[len(h.chain)-1].nextFunc = next - - return h.chain[0].invoke(ctx) -} - -// ComposeIntervalMiddleware - Composes an array of middleware into a single middleware -func ComposeIntervalMiddleware(funcs ...IntervalMiddleware) IntervalMiddleware { - mwareChain := &intervalMiddlewareChain{ - chain: make([]*chainedIntervalMiddleware, len(funcs)), - } - - var nextFunc IntervalHandler = nil - for i := len(funcs) - 1; i >= 0; i = i - 1 { - cm := &chainedIntervalMiddleware{ - fun: funcs[i], - nextFunc: nextFunc, - } - nextFunc = cm.invoke - mwareChain.chain[i] = cm - } - - return mwareChain.invoke -} diff --git a/handler/message.go b/handler/message.go deleted file mode 100644 index 6eac5ee..0000000 --- a/handler/message.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -type ( - MessageHandler = func(*MessageContext) (*MessageContext, error) - MessageMiddleware = func(*MessageContext, MessageHandler) (*MessageContext, error) -) - -func MessageDummy(ctx *MessageContext) (*MessageContext, error) { - return ctx, nil -} - -type chainedMessageMiddleware struct { - fun MessageMiddleware - nextFunc MessageHandler -} - -// automatically finalize chain with dummy function -func (c *chainedMessageMiddleware) invoke(ctx *MessageContext) (*MessageContext, error) { - if c.nextFunc == nil { - c.nextFunc = MessageDummy - } - - return c.fun(ctx, c.nextFunc) -} - -type messageMiddlewareChain struct { - chain []*chainedMessageMiddleware -} - -func (h *messageMiddlewareChain) invoke(ctx *MessageContext, next MessageHandler) (*MessageContext, error) { - // Complete the chain - h.chain[len(h.chain)-1].nextFunc = next - - return h.chain[0].invoke(ctx) -} - -// ComposeMessageMiddleware - Composes an array of middleware into a single middleware -func ComposeMessageMiddleware(funcs ...MessageMiddleware) MessageMiddleware { - mwareChain := &messageMiddlewareChain{ - chain: make([]*chainedMessageMiddleware, len(funcs)), - } - - var nextFunc MessageHandler = nil - for i := len(funcs) - 1; i >= 0; i = i - 1 { - cm := &chainedMessageMiddleware{ - fun: funcs[i], - nextFunc: nextFunc, - } - nextFunc = cm.invoke - mwareChain.chain[i] = cm - } - - return mwareChain.invoke -} diff --git a/handler/request.go b/handler/request.go deleted file mode 100644 index 1d523cc..0000000 --- a/handler/request.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -import ( - "github.com/nitrictech/go-sdk/api/storage" - v1 "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" -) - -// Http - -type HttpRequest interface { - Method() string - Path() string - Data() []byte - Query() map[string][]string - Headers() map[string][]string - PathParams() map[string]string -} - -type httpRequestImpl struct { - method string - path string - data []byte - query map[string][]string - headers map[string][]string - pathParams map[string]string -} - -func (h *httpRequestImpl) Method() string { - return h.method -} - -func (h *httpRequestImpl) Path() string { - return h.path -} - -func (h *httpRequestImpl) Data() []byte { - return h.data -} - -func (h *httpRequestImpl) Query() map[string][]string { - return h.query -} - -func (h *httpRequestImpl) Headers() map[string][]string { - return h.headers -} - -func (h *httpRequestImpl) PathParams() map[string]string { - return h.pathParams -} - -// Message - -type MessageRequest interface { - TopicName() string - Message() map[string]interface{} -} - -type messageRequestImpl struct { - topicName string - message map[string]interface{} -} - -func (m *messageRequestImpl) TopicName() string { - return m.topicName -} - -func (m *messageRequestImpl) Message() map[string]interface{} { - return m.message -} - -// Interval - -type IntervalRequest interface { - ScheduleName() string -} - -type intervalRequestImpl struct { - scheduleName string -} - -func (i *intervalRequestImpl) ScheduleName() string { - return i.scheduleName -} - -// Blob Event - -type BlobEventType string - -var BlobEventTypes = []BlobEventType{WriteNotification, DeleteNotification} - -const ( - WriteNotification BlobEventType = "write" - DeleteNotification BlobEventType = "delete" -) - -type BlobEventRequest interface { - Key() string - NotificationType() BlobEventType -} - -type blobEventRequestImpl struct { - key string - notificationType BlobEventType -} - -func (b *blobEventRequestImpl) Key() string { - return b.key -} - -func (b *blobEventRequestImpl) NotificationType() BlobEventType { - return b.notificationType -} - -// File Event - -type FileEventRequest interface { - Bucket() *storage.Bucket - NotificationType() BlobEventType -} - -type fileEventRequestImpl struct { - bucket storage.Bucket - notificationType BlobEventType -} - -func (f *fileEventRequestImpl) Bucket() storage.Bucket { - return f.bucket -} - -func (f *fileEventRequestImpl) NotificationType() BlobEventType { - return f.notificationType -} - -// Websocket - -type WebsocketEventType string - -var WebsocketEventTypes = []WebsocketEventType{WebsocketConnect, WebsocketDisconnect, WebsocketMessage} - -const ( - WebsocketConnect WebsocketEventType = "connect" - WebsocketDisconnect WebsocketEventType = "disconnect" - WebsocketMessage WebsocketEventType = "message" -) - -type WebsocketRequest interface { - SocketName() string - EventType() WebsocketEventType - ConnectionID() string - QueryParams() map[string][]string - Message() string -} - -type websocketRequestImpl struct { - socketName string - eventType WebsocketEventType - connectionId string - queryParams map[string]*v1.QueryValue - message string -} - -func (w *websocketRequestImpl) SocketName() string { - return w.socketName -} - -func (w *websocketRequestImpl) EventType() WebsocketEventType { - return w.eventType -} - -func (w *websocketRequestImpl) ConnectionID() string { - return w.connectionId -} - -func (w *websocketRequestImpl) QueryParams() map[string][]string { - queryParams := map[string][]string{} - - for k, v := range w.queryParams { - queryParams[k] = v.Value - } - - return queryParams -} - -func (w *websocketRequestImpl) Message() string { - return w.message -} diff --git a/handler/response.go b/handler/response.go deleted file mode 100644 index 7eb8c98..0000000 --- a/handler/response.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -type HttpResponse struct { - Status int - Headers map[string][]string - Body []byte -} - -type MessageResponse struct { - Success bool -} - -type IntervalResponse struct { - Success bool -} - -type BlobEventResponse struct { - Success bool -} - -type FileEventResponse struct { - Success bool -} - -type WebsocketResponse struct { - Reject bool -} diff --git a/handler/websocket.go b/handler/websocket.go deleted file mode 100644 index 41b548e..0000000 --- a/handler/websocket.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 handler - -type ( - WebsocketHandler = func(*WebsocketContext) (*WebsocketContext, error) - WebsocketMiddleware = func(*WebsocketContext, WebsocketHandler) (*WebsocketContext, error) -) - -func WebsocketDummy(ctx *WebsocketContext) (*WebsocketContext, error) { - return ctx, nil -} - -type chainedWebsocketMiddleware struct { - fun WebsocketMiddleware - nextFunc WebsocketHandler -} - -// automatically finalize chain with dummy function -func (c *chainedWebsocketMiddleware) invoke(ctx *WebsocketContext) (*WebsocketContext, error) { - if c.nextFunc == nil { - c.nextFunc = WebsocketDummy - } - - return c.fun(ctx, c.nextFunc) -} - -type websocketMiddlewareChain struct { - chain []*chainedWebsocketMiddleware -} - -func (h *websocketMiddlewareChain) invoke(ctx *WebsocketContext, next WebsocketHandler) (*WebsocketContext, error) { - // Complete the chain - h.chain[len(h.chain)-1].nextFunc = next - - return h.chain[0].invoke(ctx) -} - -// ComposeWebsocketMiddleware - Composes an array of middleware into a single middleware -func ComposeWebsocketMiddleware(funcs ...WebsocketMiddleware) WebsocketMiddleware { - mwareChain := &websocketMiddlewareChain{ - chain: make([]*chainedWebsocketMiddleware, len(funcs)), - } - - var nextFunc WebsocketHandler = nil - for i := len(funcs) - 1; i >= 0; i = i - 1 { - cm := &chainedWebsocketMiddleware{ - fun: funcs[i], - nextFunc: nextFunc, - } - nextFunc = cm.invoke - mwareChain.chain[i] = cm - } - - return mwareChain.invoke -} diff --git a/nitric/api.go b/nitric/api.go index 5c2b84f..73c6b80 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -19,44 +19,38 @@ import ( "path" "strings" - "github.com/nitrictech/go-sdk/handler" - "github.com/nitrictech/go-sdk/workers" + httpx "github.com/nitrictech/go-sdk/api/http" + apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" resourcev1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) // Route providers convenience functions to register a handler in a single method. type Route interface { - All(handler handler.HttpMiddleware, opts ...MethodOption) - Get(handler handler.HttpMiddleware, opts ...MethodOption) - Patch(handler handler.HttpMiddleware, opts ...MethodOption) - Put(handler handler.HttpMiddleware, opts ...MethodOption) - Post(handler handler.HttpMiddleware, opts ...MethodOption) - Delete(handler handler.HttpMiddleware, opts ...MethodOption) - Options(handler handler.HttpMiddleware, opts ...MethodOption) + All(handler Middleware[httpx.Ctx], opts ...MethodOption) + Get(handler Middleware[httpx.Ctx], opts ...MethodOption) + Patch(handler Middleware[httpx.Ctx], opts ...MethodOption) + Put(handler Middleware[httpx.Ctx], opts ...MethodOption) + Post(handler Middleware[httpx.Ctx], opts ...MethodOption) + Delete(handler Middleware[httpx.Ctx], opts ...MethodOption) + Options(handler Middleware[httpx.Ctx], opts ...MethodOption) ApiName() string } type route struct { path string api *api - middleware handler.HttpMiddleware + middleware Middleware[httpx.Ctx] manager Manager } -func composeRouteMiddleware(apiMiddleware handler.HttpMiddleware, routeMiddleware []handler.HttpMiddleware) handler.HttpMiddleware { - if apiMiddleware != nil && len(routeMiddleware) > 0 { - return handler.ComposeHttpMiddleware(apiMiddleware, handler.ComposeHttpMiddleware(routeMiddleware...)) - } +func composeRouteMiddleware(apiMiddleware Middleware[httpx.Ctx], routeMiddleware []Middleware[httpx.Ctx]) Middleware[httpx.Ctx] { + allMiddleware := append([]Middleware[httpx.Ctx]{apiMiddleware}, routeMiddleware...) - if len(routeMiddleware) > 0 { - return handler.ComposeHttpMiddleware(routeMiddleware...) - } - - return apiMiddleware + return Compose(allMiddleware...) } -func (a *api) NewRoute(match string, middleware ...handler.HttpMiddleware) Route { +func (a *api) NewRoute(match string, middleware ...Middleware[httpx.Ctx]) Route { r, ok := a.routes[match] if !ok { r = &route{ @@ -74,7 +68,7 @@ func (r *route) ApiName() string { return r.api.name } -func (r *route) AddMethodHandler(methods []string, middleware handler.HttpMiddleware, opts ...MethodOption) error { +func (r *route) AddMethodHandler(methods []string, middleware Middleware[httpx.Ctx], opts ...MethodOption) error { bName := path.Join(r.api.name, r.path, strings.Join(methods, "-")) // default methodOptions will contain OidcOptions passed to API instance and securityDisabled to false @@ -87,10 +81,7 @@ func (r *route) AddMethodHandler(methods []string, middleware handler.HttpMiddle o(mo) } - composedHandler := middleware - if r.middleware != nil { - composedHandler = handler.ComposeHttpMiddleware(r.middleware, middleware) - } + composedHandler := Compose(r.middleware, middleware) apiOpts := &apispb.ApiWorkerOptions{ SecurityDisabled: mo.securityDisabled, @@ -117,7 +108,7 @@ func (r *route) AddMethodHandler(methods []string, middleware handler.HttpMiddle Options: apiOpts, } - wkr := workers.NewApiWorker(&workers.ApiWorkerOpts{ + wkr := newApiWorker(&apiWorkerOpts{ RegistrationRequest: registrationRequest, Middleware: composedHandler, }) @@ -127,31 +118,31 @@ func (r *route) AddMethodHandler(methods []string, middleware handler.HttpMiddle return nil } -func (r *route) All(handler handler.HttpMiddleware, opts ...MethodOption) { +func (r *route) All(handler Middleware[httpx.Ctx], opts ...MethodOption) { r.AddMethodHandler([]string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions}, handler, opts...) } -func (r *route) Get(handler handler.HttpMiddleware, opts ...MethodOption) { +func (r *route) Get(handler Middleware[httpx.Ctx], opts ...MethodOption) { r.AddMethodHandler([]string{http.MethodGet}, handler, opts...) } -func (r *route) Post(handler handler.HttpMiddleware, opts ...MethodOption) { +func (r *route) Post(handler Middleware[httpx.Ctx], opts ...MethodOption) { r.AddMethodHandler([]string{http.MethodPost}, handler, opts...) } -func (r *route) Put(handler handler.HttpMiddleware, opts ...MethodOption) { +func (r *route) Put(handler Middleware[httpx.Ctx], opts ...MethodOption) { r.AddMethodHandler([]string{http.MethodPut}, handler, opts...) } -func (r *route) Patch(handler handler.HttpMiddleware, opts ...MethodOption) { +func (r *route) Patch(handler Middleware[httpx.Ctx], opts ...MethodOption) { r.AddMethodHandler([]string{http.MethodPatch}, handler, opts...) } -func (r *route) Delete(handler handler.HttpMiddleware, opts ...MethodOption) { +func (r *route) Delete(handler Middleware[httpx.Ctx], opts ...MethodOption) { r.AddMethodHandler([]string{http.MethodDelete}, handler, opts...) } -func (r *route) Options(handler handler.HttpMiddleware, opts ...MethodOption) { +func (r *route) Options(handler Middleware[httpx.Ctx], opts ...MethodOption) { r.AddMethodHandler([]string{http.MethodOptions}, handler, opts...) } @@ -161,13 +152,13 @@ func (r *route) Options(handler handler.HttpMiddleware, opts ...MethodOption) { // // Note: to chain middleware use handler.ComposeHttpMiddlware() type Api interface { - Get(path string, handler handler.HttpMiddleware, opts ...MethodOption) - Put(path string, handler handler.HttpMiddleware, opts ...MethodOption) - Patch(path string, handler handler.HttpMiddleware, opts ...MethodOption) - Post(path string, handler handler.HttpMiddleware, opts ...MethodOption) - Delete(path string, handler handler.HttpMiddleware, opts ...MethodOption) - Options(path string, handler handler.HttpMiddleware, opts ...MethodOption) - NewRoute(path string, middleware ...handler.HttpMiddleware) Route + Get(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + Put(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + Patch(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + Post(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + Delete(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + Options(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + NewRoute(path string, middleware ...Middleware[httpx.Ctx]) Route } type ApiDetails struct { @@ -182,7 +173,7 @@ type api struct { securityRules map[string]interface{} security []OidcOptions path string - middleware handler.HttpMiddleware + middleware Middleware[httpx.Ctx] } // NewApi Registers a new API Resource. @@ -234,7 +225,7 @@ func NewApi(name string, opts ...ApiOption) (Api, error) { // Get adds a Get method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Get(match string, handler handler.HttpMiddleware, opts ...MethodOption) { +func (a *api) Get(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { r := a.NewRoute(match) r.Get(handler, opts...) @@ -243,7 +234,7 @@ func (a *api) Get(match string, handler handler.HttpMiddleware, opts ...MethodOp // Post adds a Post method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Post(match string, handler handler.HttpMiddleware, opts ...MethodOption) { +func (a *api) Post(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { r := a.NewRoute(match) r.Post(handler, opts...) @@ -252,7 +243,7 @@ func (a *api) Post(match string, handler handler.HttpMiddleware, opts ...MethodO // Patch adds a Patch method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Patch(match string, handler handler.HttpMiddleware, opts ...MethodOption) { +func (a *api) Patch(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { r := a.NewRoute(match) r.Patch(handler, opts...) @@ -261,7 +252,7 @@ func (a *api) Patch(match string, handler handler.HttpMiddleware, opts ...Method // Put adds a Put method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Put(match string, handler handler.HttpMiddleware, opts ...MethodOption) { +func (a *api) Put(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { r := a.NewRoute(match) r.Put(handler, opts...) @@ -270,7 +261,7 @@ func (a *api) Put(match string, handler handler.HttpMiddleware, opts ...MethodOp // Delete adds a Delete method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Delete(match string, handler handler.HttpMiddleware, opts ...MethodOption) { +func (a *api) Delete(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { r := a.NewRoute(match) r.Delete(handler, opts...) @@ -279,7 +270,7 @@ func (a *api) Delete(match string, handler handler.HttpMiddleware, opts ...Metho // Options adds an Options method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Options(match string, handler handler.HttpMiddleware, opts ...MethodOption) { +func (a *api) Options(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { r := a.NewRoute(match) r.Options(handler, opts...) diff --git a/workers/api.go b/nitric/api_workers.go similarity index 82% rename from workers/api.go rename to nitric/api_workers.go index fb0b398..8183bac 100644 --- a/workers/api.go +++ b/nitric/api_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package workers +package nitric import ( "context" @@ -23,26 +23,26 @@ import ( "github.com/nitrictech/go-sdk/api/errors" "github.com/nitrictech/go-sdk/api/errors/codes" + httpx "github.com/nitrictech/go-sdk/api/http" "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/handler" v1 "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" ) -type ApiWorker struct { +type apiWorker struct { client v1.ApiClient - middleware handler.HttpMiddleware + middleware Middleware[httpx.Ctx] registrationRequest *v1.RegistrationRequest } -type ApiWorkerOpts struct { +type apiWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware handler.HttpMiddleware + Middleware Middleware[httpx.Ctx] } -var _ Worker = (*ApiWorker)(nil) +var _ streamWorker = (*apiWorker)(nil) // Start implements Worker. -func (a *ApiWorker) Start(ctx context.Context) error { +func (a *apiWorker) Start(ctx context.Context) error { initReq := &v1.ClientMessage{ Content: &v1.ClientMessage_RegistrationRequest{ RegistrationRequest: a.registrationRequest, @@ -60,7 +60,7 @@ func (a *ApiWorker) Start(ctx context.Context) error { } for { - var ctx *handler.HttpContext + var ctx *httpx.Ctx resp, err := stream.Recv() @@ -75,9 +75,9 @@ func (a *ApiWorker) Start(ctx context.Context) error { // Function connected with Nitric server fmt.Println("Function connected with Nitric server") } else if err == nil && resp.GetHttpRequest() != nil { - ctx = handler.NewHttpContext(resp) + ctx = httpx.NewCtx(resp) - ctx, err = a.middleware(ctx, handler.HttpDummy) + ctx, err = a.middleware(ctx, dummyHandler) if err != nil { ctx.WithError(err) } @@ -92,7 +92,7 @@ func (a *ApiWorker) Start(ctx context.Context) error { } } -func NewApiWorker(opts *ApiWorkerOpts) *ApiWorker { +func newApiWorker(opts *apiWorkerOpts) *apiWorker { ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) conn, err := grpc.DialContext( @@ -110,7 +110,7 @@ func NewApiWorker(opts *ApiWorkerOpts) *ApiWorker { client := v1.NewApiClient(conn) - return &ApiWorker{ + return &apiWorker{ client: client, registrationRequest: opts.RegistrationRequest, middleware: opts.Middleware, diff --git a/nitric/bucket.go b/nitric/bucket.go index d67baf1..980173a 100644 --- a/nitric/bucket.go +++ b/nitric/bucket.go @@ -19,8 +19,6 @@ import ( "strings" "github.com/nitrictech/go-sdk/api/storage" - "github.com/nitrictech/go-sdk/handler" - "github.com/nitrictech/go-sdk/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" storagepb "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" ) @@ -35,7 +33,7 @@ type bucket struct { type Bucket interface { Allow(BucketPermission, ...BucketPermission) (storage.Bucket, error) - On(handler.BlobEventType, string, ...handler.BlobEventMiddleware) + On(storage.EventType, string, ...Middleware[storage.Ctx]) } const ( @@ -104,12 +102,12 @@ func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermiss return m.storage.Bucket(b.name), nil } -func (b *bucket) On(notificationType handler.BlobEventType, notificationPrefixFilter string, middleware ...handler.BlobEventMiddleware) { +func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter string, middleware ...Middleware[storage.Ctx]) { var blobEventType storagepb.BlobEventType switch notificationType { - case handler.WriteNotification: + case storage.WriteNotification: blobEventType = storagepb.BlobEventType_Created - case handler.DeleteNotification: + case storage.DeleteNotification: blobEventType = storagepb.BlobEventType_Deleted } @@ -119,14 +117,14 @@ func (b *bucket) On(notificationType handler.BlobEventType, notificationPrefixFi KeyPrefixFilter: notificationPrefixFilter, } - composedHandler := handler.ComposeBlobEventMiddleware(middleware...) + composedHandler := Compose(middleware...) - opts := &workers.BlobEventWorkerOpts{ + opts := &bucketEventWorkerOpts{ RegistrationRequest: registrationRequest, Middleware: composedHandler, } - worker := workers.NewBlobEventWorker(opts) + worker := newBucketEventWorker(opts) b.manager.addWorker("bucketNotification:"+strings.Join([]string{ b.name, notificationPrefixFilter, string(notificationType), diff --git a/workers/blob_event.go b/nitric/bucket_workers.go similarity index 82% rename from workers/blob_event.go rename to nitric/bucket_workers.go index 5f656ca..50b226e 100644 --- a/workers/blob_event.go +++ b/nitric/bucket_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package workers +package nitric import ( "context" @@ -23,23 +23,23 @@ import ( "github.com/nitrictech/go-sdk/api/errors" "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/api/storage" "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/handler" v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" ) -type BlobEventWorker struct { +type bucketEventWorker struct { client v1.StorageListenerClient registrationRequest *v1.RegistrationRequest - middleware handler.BlobEventMiddleware + middleware Middleware[storage.Ctx] } -type BlobEventWorkerOpts struct { +type bucketEventWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware handler.BlobEventMiddleware + Middleware Middleware[storage.Ctx] } // Start implements Worker. -func (b *BlobEventWorker) Start(ctx context.Context) error { +func (b *bucketEventWorker) Start(ctx context.Context) error { initReq := &v1.ClientMessage{ Content: &v1.ClientMessage_RegistrationRequest{ RegistrationRequest: b.registrationRequest, @@ -57,7 +57,7 @@ func (b *BlobEventWorker) Start(ctx context.Context) error { return err } for { - var ctx *handler.BlobEventContext + var ctx *storage.Ctx resp, err := stream.Recv() @@ -72,8 +72,8 @@ func (b *BlobEventWorker) Start(ctx context.Context) error { // Blob Notification has connected with Nitric server fmt.Println("BlobEventWorker connected with Nitric server") } else if err == nil && resp.GetBlobEventRequest() != nil { - ctx = handler.NewBlobEventContext(resp) - ctx, err = b.middleware(ctx, handler.BlobEventDummy) + ctx = storage.NewCtx(resp) + ctx, err = b.middleware(ctx, dummyHandler) if err != nil { ctx.WithError(err) } @@ -88,7 +88,7 @@ func (b *BlobEventWorker) Start(ctx context.Context) error { } } -func NewBlobEventWorker(opts *BlobEventWorkerOpts) *BlobEventWorker { +func newBucketEventWorker(opts *bucketEventWorkerOpts) *bucketEventWorker { ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) conn, err := grpc.DialContext( @@ -106,7 +106,7 @@ func NewBlobEventWorker(opts *BlobEventWorkerOpts) *BlobEventWorker { client := v1.NewStorageListenerClient(conn) - return &BlobEventWorker{ + return &bucketEventWorker{ client: client, registrationRequest: opts.RegistrationRequest, middleware: opts.Middleware, diff --git a/nitric/manager.go b/nitric/manager.go index d906655..d594600 100644 --- a/nitric/manager.go +++ b/nitric/manager.go @@ -32,14 +32,13 @@ import ( "github.com/nitrictech/go-sdk/api/storage" "github.com/nitrictech/go-sdk/api/topics" "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) // Manager is the top level object that resources are created on. type Manager interface { Run() error - addWorker(name string, s workers.Worker) + addWorker(name string, s streamWorker) resourceServiceClient() (v1.ResourcesClient, error) registerResource(request *v1.ResourceDeclareRequest) <-chan RegisterResult registerPolicy(res *v1.ResourceIdentifier, actions ...v1.Action) (*manager, error) @@ -51,7 +50,7 @@ type RegisterResult struct { } type manager struct { - workers map[string]workers.Worker + workers map[string]streamWorker conn grpc.ClientConnInterface connMutex sync.Mutex @@ -70,11 +69,11 @@ var defaultManager = New() // resources.NewApi() and the like. These use a default manager instance. func New() Manager { return &manager{ - workers: map[string]workers.Worker{}, + workers: map[string]streamWorker{}, } } -func (m *manager) addWorker(name string, s workers.Worker) { +func (m *manager) addWorker(name string, s streamWorker) { m.workers[name] = s } @@ -159,7 +158,7 @@ func (m *manager) Run() error { for _, worker := range m.workers { wg.Add(1) - go func(s workers.Worker) { + go func(s streamWorker) { defer wg.Done() if err := s.Start(context.TODO()); err != nil { diff --git a/nitric/middleware.go b/nitric/middleware.go index a4a50ad..c80332d 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -10,7 +10,7 @@ type chainedMiddleware[T any] struct { nextFunc Handler[T] } -func DummyHandler[T any](ctx *T) (*T, error) { +func dummyHandler[T any](ctx *T) (*T, error) { return ctx, nil } @@ -18,7 +18,7 @@ func (c *chainedMiddleware[T]) invoke(ctx *T) (*T, error) { // Chains are left open-ended so middleware can continue to be linked // If the chain is incomplete, set a chained dummy handler for safety if c.nextFunc == nil { - c.nextFunc = DummyHandler[T] + c.nextFunc = dummyHandler[T] } return c.fun(ctx, c.nextFunc) diff --git a/nitric/options.go b/nitric/options.go index d74094b..787851d 100644 --- a/nitric/options.go +++ b/nitric/options.go @@ -15,7 +15,7 @@ package nitric import ( - "github.com/nitrictech/go-sdk/handler" + "github.com/nitrictech/go-sdk/api/http" ) type ( @@ -44,12 +44,12 @@ func OidcRule(name string, issuer string, audiences []string) SecurityOption { } } -func WithMiddleware(middleware ...handler.HttpMiddleware) ApiOption { +func WithMiddleware(middleware ...Middleware[http.Ctx]) ApiOption { return func(api *api) { if api.middleware != nil { - api.middleware = handler.ComposeHttpMiddleware(api.middleware, handler.ComposeHttpMiddleware(middleware...)) + api.middleware = Compose(api.middleware, Compose(middleware...)) } else { - api.middleware = handler.ComposeHttpMiddleware(middleware...) + api.middleware = Compose(middleware...) } } } diff --git a/nitric/schedule.go b/nitric/schedule.go index 6dfd516..80243a4 100644 --- a/nitric/schedule.go +++ b/nitric/schedule.go @@ -17,14 +17,13 @@ package nitric import ( "strings" - "github.com/nitrictech/go-sdk/handler" - "github.com/nitrictech/go-sdk/workers" + "github.com/nitrictech/go-sdk/api/schedules" schedulespb "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) type Schedule interface { - Cron(cron string, middleware ...handler.IntervalMiddleware) - Every(rate string, middleware ...handler.IntervalMiddleware) + Cron(cron string, middleware ...Middleware[schedules.Ctx]) + Every(rate string, middleware ...Middleware[schedules.Ctx]) } type schedule struct { @@ -43,7 +42,7 @@ func NewSchedule(name string) Schedule { } // Run middleware at a certain interval defined by the cronExpression. -func (s *schedule) Cron(cron string, middleware ...handler.IntervalMiddleware) { +func (s *schedule) Cron(cron string, middleware ...Middleware[schedules.Ctx]) { scheduleCron := &schedulespb.ScheduleCron{ Expression: cron, } @@ -55,14 +54,14 @@ func (s *schedule) Cron(cron string, middleware ...handler.IntervalMiddleware) { }, } - composeHandler := handler.ComposeIntervalMiddleware(middleware...) + composeHandler := Compose(middleware...) - opts := &workers.IntervalWorkerOpts{ + opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, Middleware: composeHandler, } - worker := workers.NewIntervalWorker(opts) + worker := newScheduleWorker(opts) s.manager.addWorker("IntervalWorkerCron:"+strings.Join([]string{ s.name, cron, @@ -70,7 +69,7 @@ func (s *schedule) Cron(cron string, middleware ...handler.IntervalMiddleware) { } // Run middleware at a certain interval defined by the rate. The rate is e.g. '7 days'. All rates accept a number and a frequency. Valid frequencies are 'days', 'hours' or 'minutes'. -func (s *schedule) Every(rate string, middleware ...handler.IntervalMiddleware) { +func (s *schedule) Every(rate string, middleware ...Middleware[schedules.Ctx]) { scheduleEvery := &schedulespb.ScheduleEvery{ Rate: rate, } @@ -82,14 +81,14 @@ func (s *schedule) Every(rate string, middleware ...handler.IntervalMiddleware) }, } - composeHandler := handler.ComposeIntervalMiddleware(middleware...) + composeHandler := Compose(middleware...) - opts := &workers.IntervalWorkerOpts{ + opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, Middleware: composeHandler, } - worker := workers.NewIntervalWorker(opts) + worker := newScheduleWorker(opts) s.manager.addWorker("IntervalWorkerEvery:"+strings.Join([]string{ s.name, rate, diff --git a/workers/interval.go b/nitric/schedule_workers.go similarity index 82% rename from workers/interval.go rename to nitric/schedule_workers.go index 28597c0..9267391 100644 --- a/workers/interval.go +++ b/nitric/schedule_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package workers +package nitric import ( "context" @@ -23,23 +23,23 @@ import ( "github.com/nitrictech/go-sdk/api/errors" "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/api/schedules" "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/handler" v1 "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) -type IntervalWorker struct { +type scheduleWorker struct { client v1.SchedulesClient registrationRequest *v1.RegistrationRequest - middleware handler.IntervalMiddleware + middleware Middleware[schedules.Ctx] } -type IntervalWorkerOpts struct { +type scheduleWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware handler.IntervalMiddleware + Middleware Middleware[schedules.Ctx] } // Start implements Worker. -func (i *IntervalWorker) Start(ctx context.Context) error { +func (i *scheduleWorker) Start(ctx context.Context) error { initReq := &v1.ClientMessage{ Content: &v1.ClientMessage_RegistrationRequest{ RegistrationRequest: i.registrationRequest, @@ -57,7 +57,7 @@ func (i *IntervalWorker) Start(ctx context.Context) error { return err } for { - var ctx *handler.IntervalContext + var ctx *schedules.Ctx resp, err := stream.Recv() @@ -72,8 +72,8 @@ func (i *IntervalWorker) Start(ctx context.Context) error { // Interval worker has connected with Nitric server fmt.Println("IntervalWorker connected with Nitric server") } else if err == nil && resp.GetIntervalRequest() != nil { - ctx = handler.NewIntervalContext(resp) - ctx, err = i.middleware(ctx, handler.IntervalDummy) + ctx = schedules.NewCtx(resp) + ctx, err = i.middleware(ctx, dummyHandler) if err != nil { ctx.WithError(err) } @@ -88,7 +88,7 @@ func (i *IntervalWorker) Start(ctx context.Context) error { } } -func NewIntervalWorker(opts *IntervalWorkerOpts) *IntervalWorker { +func newScheduleWorker(opts *scheduleWorkerOpts) *scheduleWorker { ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) conn, err := grpc.DialContext( @@ -106,7 +106,7 @@ func NewIntervalWorker(opts *IntervalWorkerOpts) *IntervalWorker { client := v1.NewSchedulesClient(conn) - return &IntervalWorker{ + return &scheduleWorker{ client: client, registrationRequest: opts.RegistrationRequest, middleware: opts.Middleware, diff --git a/nitric/topic.go b/nitric/topic.go index 0bd9431..fefb0bd 100644 --- a/nitric/topic.go +++ b/nitric/topic.go @@ -18,8 +18,6 @@ import ( "fmt" "github.com/nitrictech/go-sdk/api/topics" - "github.com/nitrictech/go-sdk/handler" - "github.com/nitrictech/go-sdk/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" @@ -41,7 +39,7 @@ type SubscribableTopic interface { Allow(TopicPermission, ...TopicPermission) (Topic, error) // Subscribe will register and start a subscription handler that will be called for all events from this topic. - Subscribe(...handler.MessageMiddleware) + Subscribe(...Middleware[topics.Ctx]) } type topic struct { @@ -113,17 +111,17 @@ func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...Top }, nil } -func (t *subscribableTopic) Subscribe(middleware ...handler.MessageMiddleware) { +func (t *subscribableTopic) Subscribe(middleware ...Middleware[topics.Ctx]) { registrationRequest := &topicspb.RegistrationRequest{ TopicName: t.name, } - composeHandler := handler.ComposeMessageMiddleware(middleware...) + composeHandler := Compose(middleware...) - opts := &workers.SubscriptionWorkerOpts{ + opts := &subscriptionWorkerOpts{ RegistrationRequest: registrationRequest, Middleware: composeHandler, } - worker := workers.NewSubscriptionWorker(opts) + worker := newSubscriptionWorker(opts) t.manager.addWorker("SubscriptionWorker:"+t.name, worker) } diff --git a/workers/subscription.go b/nitric/topic_workers.go similarity index 82% rename from workers/subscription.go rename to nitric/topic_workers.go index 8ba2c94..c4e8c49 100644 --- a/workers/subscription.go +++ b/nitric/topic_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package workers +package nitric import ( "context" @@ -23,23 +23,23 @@ import ( "github.com/nitrictech/go-sdk/api/errors" "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/api/topics" "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/handler" v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" ) -type SubscriptionWorker struct { +type subscriptionWorker struct { client v1.SubscriberClient registrationRequest *v1.RegistrationRequest - middleware handler.MessageMiddleware + middleware Middleware[topics.Ctx] } -type SubscriptionWorkerOpts struct { +type subscriptionWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware handler.MessageMiddleware + Middleware Middleware[topics.Ctx] } // Start implements Worker. -func (s *SubscriptionWorker) Start(ctx context.Context) error { +func (s *subscriptionWorker) Start(ctx context.Context) error { initReq := &v1.ClientMessage{ Content: &v1.ClientMessage_RegistrationRequest{ RegistrationRequest: s.registrationRequest, @@ -57,7 +57,7 @@ func (s *SubscriptionWorker) Start(ctx context.Context) error { return err } for { - var ctx *handler.MessageContext + var ctx *topics.Ctx resp, err := stream.Recv() @@ -72,8 +72,8 @@ func (s *SubscriptionWorker) Start(ctx context.Context) error { // Subscription worker has connected with Nitric server fmt.Println("SubscriptionWorker connected with Nitric server") } else if err == nil && resp.GetMessageRequest() != nil { - ctx = handler.NewMessageContext(resp) - ctx, err = s.middleware(ctx, handler.MessageDummy) + ctx = topics.NewCtx(resp) + ctx, err = s.middleware(ctx, dummyHandler) if err != nil { ctx.WithError(err) } @@ -88,7 +88,7 @@ func (s *SubscriptionWorker) Start(ctx context.Context) error { } } -func NewSubscriptionWorker(opts *SubscriptionWorkerOpts) *SubscriptionWorker { +func newSubscriptionWorker(opts *subscriptionWorkerOpts) *subscriptionWorker { ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) conn, err := grpc.DialContext( @@ -106,7 +106,7 @@ func NewSubscriptionWorker(opts *SubscriptionWorkerOpts) *SubscriptionWorker { client := v1.NewSubscriberClient(conn) - return &SubscriptionWorker{ + return &subscriptionWorker{ client: client, registrationRequest: opts.RegistrationRequest, middleware: opts.Middleware, diff --git a/nitric/websocket.go b/nitric/websocket.go index 944ae96..261de30 100644 --- a/nitric/websocket.go +++ b/nitric/websocket.go @@ -18,15 +18,14 @@ import ( "context" "strings" - "github.com/nitrictech/go-sdk/handler" - "github.com/nitrictech/go-sdk/workers" + "github.com/nitrictech/go-sdk/api/websockets" resourcesv1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" websocketsv1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) type Websocket interface { Name() string - On(eventType handler.WebsocketEventType, mwares ...handler.WebsocketMiddleware) + On(eventType websockets.EventType, mwares ...Middleware[websockets.Ctx]) Send(ctx context.Context, connectionId string, message []byte) error Close(ctx context.Context, connectionId string) error } @@ -71,13 +70,12 @@ func (w *websocket) Name() string { return w.name } -func (w *websocket) On(eventType handler.WebsocketEventType, middleware ...handler.WebsocketMiddleware) { - // mapping handler.WebsocketEventType to protobuf requirement i.e websocketsv1.WebsocketEventType +func (w *websocket) On(eventType websockets.EventType, middleware ...Middleware[websockets.Ctx]) { var _eventType websocketsv1.WebsocketEventType switch eventType { - case handler.WebsocketDisconnect: + case websockets.EventType_Disconnect: _eventType = websocketsv1.WebsocketEventType_Disconnect - case handler.WebsocketMessage: + case websockets.EventType_Message: _eventType = websocketsv1.WebsocketEventType_Message default: _eventType = websocketsv1.WebsocketEventType_Connect @@ -87,14 +85,14 @@ func (w *websocket) On(eventType handler.WebsocketEventType, middleware ...handl SocketName: w.name, EventType: _eventType, } - composeHandler := handler.ComposeWebsocketMiddleware(middleware...) + composeHandler := Compose(middleware...) - opts := &workers.WebsocketWorkerOpts{ + opts := &websocketWorkerOpts{ RegistrationRequest: registrationRequest, Middleware: composeHandler, } - worker := workers.NewWebsocketWorker(opts) + worker := newWebsocketWorker(opts) w.manager.addWorker("WebsocketWorker:"+strings.Join([]string{ w.name, string(eventType), diff --git a/workers/websocket.go b/nitric/websocket_workers.go similarity index 82% rename from workers/websocket.go rename to nitric/websocket_workers.go index ec16e67..1b7c834 100644 --- a/workers/websocket.go +++ b/nitric/websocket_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package workers +package nitric import ( "context" @@ -23,23 +23,23 @@ import ( "github.com/nitrictech/go-sdk/api/errors" "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/api/websockets" "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/handler" v1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) -type WebsocketWorker struct { +type websocketWorker struct { client v1.WebsocketHandlerClient registrationRequest *v1.RegistrationRequest - middleware handler.WebsocketMiddleware + middleware Middleware[websockets.Ctx] } -type WebsocketWorkerOpts struct { +type websocketWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware handler.WebsocketMiddleware + Middleware Middleware[websockets.Ctx] } // Start implements Worker. -func (w *WebsocketWorker) Start(ctx context.Context) error { +func (w *websocketWorker) Start(ctx context.Context) error { initReq := &v1.ClientMessage{ Content: &v1.ClientMessage_RegistrationRequest{ RegistrationRequest: w.registrationRequest, @@ -57,7 +57,7 @@ func (w *WebsocketWorker) Start(ctx context.Context) error { return err } for { - var ctx *handler.WebsocketContext + var ctx *websockets.Ctx resp, err := stream.Recv() @@ -72,8 +72,8 @@ func (w *WebsocketWorker) Start(ctx context.Context) error { // Blob Notification has connected with Nitric server fmt.Println("WebsocketWorker connected with Nitric server") } else if err == nil && resp.GetWebsocketEventRequest() != nil { - ctx = handler.NewWebsocketContext(resp) - ctx, err = w.middleware(ctx, handler.WebsocketDummy) + ctx = websockets.NewCtx(resp) + ctx, err = w.middleware(ctx, dummyHandler) if err != nil { ctx.WithError(err) } @@ -88,7 +88,7 @@ func (w *WebsocketWorker) Start(ctx context.Context) error { } } -func NewWebsocketWorker(opts *WebsocketWorkerOpts) *WebsocketWorker { +func newWebsocketWorker(opts *websocketWorkerOpts) *websocketWorker { ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) conn, err := grpc.DialContext( @@ -106,7 +106,7 @@ func NewWebsocketWorker(opts *WebsocketWorkerOpts) *WebsocketWorker { client := v1.NewWebsocketHandlerClient(conn) - return &WebsocketWorker{ + return &websocketWorker{ client: client, registrationRequest: opts.RegistrationRequest, middleware: opts.Middleware, diff --git a/workers/workers.go b/nitric/workers.go similarity index 93% rename from workers/workers.go rename to nitric/workers.go index c740611..2f7e131 100644 --- a/workers/workers.go +++ b/nitric/workers.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package workers +package nitric import "context" -type Worker interface { +type streamWorker interface { Start(context.Context) error } diff --git a/tools/tools.go b/tools/tools.go index f34dec9..444d855 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build tools +// +build tools + package tools import ( From 6f8e0e7ae1ccb88d2e873c17388f758981a620e6 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 14:19:59 +1000 Subject: [PATCH 04/42] fmt --- .golangci.yml | 3 + api/http/context.go | 14 ++ api/http/request.go | 14 ++ api/http/response.go | 14 ++ api/keyvalue/keyvalue.go | 10 +- api/keyvalue/store_test.go | 1 - api/queues/queue_test.go | 4 +- api/queues/queues.go | 10 +- api/queues/queues_test.go | 2 +- api/queues/task_test.go | 2 +- api/schedules/context.go | 14 ++ api/schedules/request.go | 14 ++ api/schedules/response.go | 14 ++ api/secrets/secrets.go | 10 +- api/secrets/secrets_test.go | 1 - api/storage/bucket_test.go | 2 +- api/storage/context.go | 24 ++- api/storage/file_test.go | 2 +- api/storage/request.go | 43 +++-- api/storage/response.go | 14 ++ api/storage/storage.go | 10 +- api/topics/context.go | 14 ++ api/topics/request.go | 14 ++ api/topics/response.go | 14 ++ api/topics/topics.go | 10 +- api/websockets/context.go | 14 ++ api/websockets/request.go | 14 ++ api/websockets/response.go | 14 ++ constants/grpc.go | 2 - go.mod | 169 +++++++++-------- go.sum | 354 ++++++++++++++++++------------------ licenses.go | 1 - nitric/api.go | 19 +- nitric/api_workers.go | 11 +- nitric/bucket_workers.go | 11 +- nitric/manager.go | 8 +- nitric/middleware.go | 20 +- nitric/schedule_workers.go | 11 +- nitric/topic_workers.go | 12 +- nitric/websocket_workers.go | 11 +- workers/file_event.go | 15 -- 41 files changed, 551 insertions(+), 409 deletions(-) delete mode 100644 workers/file_event.go diff --git a/.golangci.yml b/.golangci.yml index 631ef01..336c9a5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,6 +23,9 @@ linters: issues: max-issues-per-linter: 0 max-same-issues: 0 + exclude-files: + - tools/tools.go + - doc.go exclude-rules: - path: _test\.go linters: diff --git a/api/http/context.go b/api/http/context.go index a37f2cd..04a992b 100644 --- a/api/http/context.go +++ b/api/http/context.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 http import apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" diff --git a/api/http/request.go b/api/http/request.go index 83b044b..7060169 100644 --- a/api/http/request.go +++ b/api/http/request.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 http type Request interface { diff --git a/api/http/response.go b/api/http/response.go index 62a4849..0b517da 100644 --- a/api/http/response.go +++ b/api/http/response.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 http type Response struct { diff --git a/api/keyvalue/keyvalue.go b/api/keyvalue/keyvalue.go index 93a0792..0875f5d 100644 --- a/api/keyvalue/keyvalue.go +++ b/api/keyvalue/keyvalue.go @@ -15,8 +15,6 @@ package keyvalue import ( - "context" - "google.golang.org/grpc" "github.com/nitrictech/go-sdk/api/errors" @@ -44,13 +42,7 @@ func (k *keyValueImpl) Store(name string) Store { // New - Construct a new Key Value Store Client with default options func New() (KeyValue, error) { - ctx, _ := context.WithTimeout(context.Background(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/api/keyvalue/store_test.go b/api/keyvalue/store_test.go index 77fb16a..0a27a94 100644 --- a/api/keyvalue/store_test.go +++ b/api/keyvalue/store_test.go @@ -139,7 +139,6 @@ var _ = Describe("KeyValue Store API", func() { Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) }) }) - }) Describe("Delete", func() { diff --git a/api/queues/queue_test.go b/api/queues/queue_test.go index f0107c6..fb2252b 100644 --- a/api/queues/queue_test.go +++ b/api/queues/queue_test.go @@ -110,7 +110,7 @@ var _ = Describe("Queue interface", func() { ).Times(1) }) - It("should recieve a message from []*FailedMessage", func() { + It("should receive a message from []*FailedMessage", func() { failedMessages, err := q.Enqueue(ctx, messages) Expect(err).ToNot(HaveOccurred()) Expect(failedMessages).To(HaveLen(1)) @@ -227,4 +227,4 @@ var _ = Describe("Queue interface", func() { }) }) }) -}) \ No newline at end of file +}) diff --git a/api/queues/queues.go b/api/queues/queues.go index 4ce23f9..f490d5d 100644 --- a/api/queues/queues.go +++ b/api/queues/queues.go @@ -15,8 +15,6 @@ package queues import ( - "context" - "google.golang.org/grpc" "github.com/nitrictech/go-sdk/api/errors" @@ -43,13 +41,7 @@ func (q *queuesImpl) Queue(name string) Queue { // New - Construct a new Queueing Client with default options func New() (Queues, error) { - ctx, _ := context.WithTimeout(context.Background(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/api/queues/queues_test.go b/api/queues/queues_test.go index 845cf65..4f25d8b 100644 --- a/api/queues/queues_test.go +++ b/api/queues/queues_test.go @@ -96,4 +96,4 @@ var _ = Describe("Queues API", func() { // TODO: }) }) -}) \ No newline at end of file +}) diff --git a/api/queues/task_test.go b/api/queues/task_test.go index cc44d36..798c652 100644 --- a/api/queues/task_test.go +++ b/api/queues/task_test.go @@ -124,4 +124,4 @@ var _ = Describe("Helper functions", func() { Expect(convertedMessage).To(Equal(message)) }) }) -}) \ No newline at end of file +}) diff --git a/api/schedules/context.go b/api/schedules/context.go index f1d165a..d215937 100644 --- a/api/schedules/context.go +++ b/api/schedules/context.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 schedules import schedulespb "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" diff --git a/api/schedules/request.go b/api/schedules/request.go index 3b95313..1c2bb42 100644 --- a/api/schedules/request.go +++ b/api/schedules/request.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 schedules type Request interface { diff --git a/api/schedules/response.go b/api/schedules/response.go index a46caec..05f6e2b 100644 --- a/api/schedules/response.go +++ b/api/schedules/response.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 schedules type Response struct { diff --git a/api/secrets/secrets.go b/api/secrets/secrets.go index 93357dd..0df759a 100644 --- a/api/secrets/secrets.go +++ b/api/secrets/secrets.go @@ -15,8 +15,6 @@ package secrets import ( - "context" - "google.golang.org/grpc" "github.com/nitrictech/go-sdk/api/errors" @@ -44,13 +42,7 @@ func (s *secretsImpl) Secret(name string) SecretRef { // New - Create a new Secrets client func New() (Secrets, error) { - ctx, _ := context.WithTimeout(context.Background(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/api/secrets/secrets_test.go b/api/secrets/secrets_test.go index c4a5270..4884baa 100644 --- a/api/secrets/secrets_test.go +++ b/api/secrets/secrets_test.go @@ -76,7 +76,6 @@ var _ = Describe("Secrets API", func() { When("Constructing a new Secrets client with no rpc server available", func() { BeforeEach(func() { os.Setenv("NITRIC_SERVICE_DIAL_TIMEOUT", "10") - }) AfterEach(func() { os.Unsetenv("NITRIC_SERVICE_DIAL_TIMEOUT") diff --git a/api/storage/bucket_test.go b/api/storage/bucket_test.go index 0cf5bab..ee0f6b4 100644 --- a/api/storage/bucket_test.go +++ b/api/storage/bucket_test.go @@ -69,7 +69,7 @@ var _ = Describe("Bucket", func() { fileI, ok = file.(*fileImpl) }) - It("it should succesfully return File Instance", func() { + It("it should successfully return File Instance", func() { By("returning an fileImpl instance") Expect(ok).To(BeTrue()) diff --git a/api/storage/context.go b/api/storage/context.go index ea3c1a9..ffc3127 100644 --- a/api/storage/context.go +++ b/api/storage/context.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 storage import storagepb "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" @@ -40,8 +54,8 @@ func (c *Ctx) WithError(err error) { } } -type FileCtx struct { - Request FileRequest - Response *FileResponse - Extras map[string]interface{} -} +// type FileCtx struct { +// Request FileRequest +// Response *FileResponse +// Extras map[string]interface{} +// } diff --git a/api/storage/file_test.go b/api/storage/file_test.go index d216514..9f6dc23 100644 --- a/api/storage/file_test.go +++ b/api/storage/file_test.go @@ -484,7 +484,7 @@ var _ = Describe("PresignUrlOptions", func() { It("should return an error", func() { err := p.isValid() - By("occurance of error") + By("occurrence of error") Expect(err).To(HaveOccurred()) By("containing appropriate error message") diff --git a/api/storage/request.go b/api/storage/request.go index e8b10ab..f987e2c 100644 --- a/api/storage/request.go +++ b/api/storage/request.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 storage type EventType string @@ -29,20 +43,21 @@ func (b *requestImpl) NotificationType() EventType { // File Event -type FileRequest interface { - Bucket() *Bucket - NotificationType() EventType -} +// XXX: File requests currently not implemented +// type FileRequest interface { +// Bucket() *Bucket +// NotificationType() EventType +// } -type fileRequestImpl struct { - bucket Bucket - notificationType EventType -} +// type fileRequestImpl struct { +// bucket Bucket +// notificationType EventType +// } -func (f *fileRequestImpl) Bucket() Bucket { - return f.bucket -} +// func (f *fileRequestImpl) Bucket() Bucket { +// return f.bucket +// } -func (f *fileRequestImpl) NotificationType() EventType { - return f.notificationType -} +// func (f *fileRequestImpl) NotificationType() EventType { +// return f.notificationType +// } diff --git a/api/storage/response.go b/api/storage/response.go index 7e92d5a..5ccbab3 100644 --- a/api/storage/response.go +++ b/api/storage/response.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 storage type Response struct { diff --git a/api/storage/storage.go b/api/storage/storage.go index 11fe0de..927a556 100644 --- a/api/storage/storage.go +++ b/api/storage/storage.go @@ -15,8 +15,6 @@ package storage import ( - "context" - "google.golang.org/grpc" "github.com/nitrictech/go-sdk/api/errors" @@ -44,13 +42,7 @@ func (s *storageImpl) Bucket(name string) Bucket { // New - Create a new Storage client with default options func New() (Storage, error) { - ctx, _ := context.WithTimeout(context.Background(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/api/topics/context.go b/api/topics/context.go index 548db10..bb2e247 100644 --- a/api/topics/context.go +++ b/api/topics/context.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 topics import topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" diff --git a/api/topics/request.go b/api/topics/request.go index 26735e7..9d147cb 100644 --- a/api/topics/request.go +++ b/api/topics/request.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 topics type Request interface { diff --git a/api/topics/response.go b/api/topics/response.go index 338023c..f9ecdac 100644 --- a/api/topics/response.go +++ b/api/topics/response.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 topics type Response struct { diff --git a/api/topics/topics.go b/api/topics/topics.go index ea9b379..4c95fc7 100644 --- a/api/topics/topics.go +++ b/api/topics/topics.go @@ -15,8 +15,6 @@ package topics import ( - "context" - "google.golang.org/grpc" "github.com/nitrictech/go-sdk/api/errors" @@ -46,13 +44,7 @@ func (s *topicsImpl) Topic(name string) Topic { // New - Construct a new Eventing Client with default options func New() (Topics, error) { - ctx, _ := context.WithTimeout(context.Background(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { return nil, errors.NewWithCause(codes.Unavailable, "Unable to dial Events service", err) } diff --git a/api/websockets/context.go b/api/websockets/context.go index 5f44062..06aee98 100644 --- a/api/websockets/context.go +++ b/api/websockets/context.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 websockets import websocketspb "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" diff --git a/api/websockets/request.go b/api/websockets/request.go index a303c0e..fa4dc55 100644 --- a/api/websockets/request.go +++ b/api/websockets/request.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 websockets import ( diff --git a/api/websockets/response.go b/api/websockets/response.go index 7150d3b..1cc3f86 100644 --- a/api/websockets/response.go +++ b/api/websockets/response.go @@ -1,3 +1,17 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 websockets type Response struct { diff --git a/constants/grpc.go b/constants/grpc.go index 353c136..afa6aa7 100644 --- a/constants/grpc.go +++ b/constants/grpc.go @@ -22,8 +22,6 @@ import ( // DefaultOptions - Provides option defaults for creating a gRPC service connection with the Nitric Membrane func DefaultOptions() []grpc.DialOption { return []grpc.DialOption{ - // TODO: Look at authentication config with membrane - grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials()), } } diff --git a/go.mod b/go.mod index 6127b70..6014421 100644 --- a/go.mod +++ b/go.mod @@ -1,33 +1,32 @@ module github.com/nitrictech/go-sdk -go 1.21 +go 1.22.1 -toolchain go1.21.4 +toolchain go1.23.0 require ( github.com/golang/mock v1.7.0-rc.1 github.com/golang/protobuf v1.5.3 - github.com/golangci/golangci-lint v1.56.1 + github.com/golangci/golangci-lint v1.61.0 github.com/google/addlicense v1.1.1 github.com/missionMeteora/toolkit v0.0.0-20170713173850-88364e3ef8cc github.com/nitrictech/nitric/core v0.0.0-20240501153359-997c6077b84f github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.28.1 + github.com/onsi/gomega v1.34.2 github.com/uw-labs/lichen v0.1.7 - google.golang.org/grpc v1.59.0 + google.golang.org/grpc v1.66.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 ) require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect 4d63.com/gochecknoglobals v0.2.1 // indirect - github.com/Abirdcfly/dupword v0.0.13 // indirect - github.com/Antonboom/errname v0.1.12 // indirect - github.com/Antonboom/nilnil v0.1.7 // indirect - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/Abirdcfly/dupword v0.1.1 // indirect + github.com/Antonboom/errname v0.1.13 // indirect + github.com/Antonboom/nilnil v0.1.9 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/Djarvur/go-err113 v0.1.0 // indirect - github.com/Masterminds/semver v1.5.0 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/ashanbrown/forbidigo v1.6.0 // indirect @@ -39,44 +38,38 @@ require ( github.com/breml/bidichk v0.2.7 // indirect github.com/breml/errchkjson v0.3.6 // indirect github.com/butuzov/ireturn v0.3.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/chavacava/garif v0.1.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/daixiang0/gci v0.12.1 // indirect + github.com/daixiang0/gci v0.13.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/denis-tingaikin/go-header v0.4.3 // indirect - github.com/esimonov/ifshort v1.0.4 // indirect + github.com/denis-tingaikin/go-header v0.5.0 // indirect github.com/ettle/strcase v0.2.0 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.4 // indirect + github.com/firefart/nonamedreturns v1.0.5 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/go-critic/go-critic v0.11.0 // indirect + github.com/go-critic/go-critic v0.11.4 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect - github.com/go-toolsmith/astequal v1.1.0 // indirect + github.com/go-toolsmith/astequal v1.2.0 // indirect github.com/go-toolsmith/astfmt v1.1.0 // indirect github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.8.1 // indirect - github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect + github.com/gofrs/flock v0.12.1 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect - github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e // indirect - github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect - github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect - github.com/golangci/misspell v0.4.1 // indirect - github.com/golangci/revgrep v0.5.2 // indirect - github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect + github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 // indirect + github.com/golangci/misspell v0.6.0 // indirect + github.com/golangci/revgrep v0.5.3 // indirect + github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/gordonklaus/ineffassign v0.1.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect @@ -84,23 +77,22 @@ require ( github.com/gostaticanalysis/nilerr v0.1.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jgautheron/goconst v1.7.0 // indirect + github.com/jgautheron/goconst v1.7.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect github.com/julz/importas v0.1.0 // indirect github.com/kisielk/errcheck v1.7.0 // indirect - github.com/kisielk/gotool v1.0.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.4 // indirect + github.com/kkHAIKE/contextcheck v1.1.5 // indirect github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.9 // indirect + github.com/kunwardeep/paralleltest v1.0.10 // indirect github.com/kyoh86/exportloopref v0.1.11 // indirect - github.com/ldez/gomoddirectives v0.2.3 // indirect + github.com/ldez/gomoddirectives v0.2.4 // indirect github.com/ldez/tagliatelle v0.5.0 // indirect - github.com/leonklingele/grouper v1.1.1 // indirect + github.com/leonklingele/grouper v1.1.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lufeee/execinquery v1.2.1 // indirect github.com/magiconair/properties v1.8.6 // indirect @@ -111,117 +103,122 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect - github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.3.7 // indirect + github.com/mgechev/revive v1.3.9 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/moricho/tparallel v0.3.1 // indirect + github.com/moricho/tparallel v0.3.2 // indirect github.com/muesli/termenv v0.15.2 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.15.2 // indirect + github.com/nunnatsa/ginkgolinter v0.16.2 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/polyfloyd/go-errorlint v1.4.8 // indirect + github.com/polyfloyd/go-errorlint v1.6.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - github.com/quasilyte/go-ruleguard v0.4.0 // indirect + github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/ryancurrah/gomodguard v1.3.0 // indirect + github.com/ryancurrah/gomodguard v1.3.5 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.24.0 // indirect - github.com/securego/gosec/v2 v2.18.2 // indirect + github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect + github.com/securego/gosec/v2 v2.21.2 // indirect github.com/sergi/go-diff v1.3.1 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sivchari/nosnakecase v1.7.0 // indirect - github.com/sivchari/tenv v1.7.1 // indirect + github.com/sivchari/tenv v1.10.0 // indirect github.com/sonatard/noctx v0.0.2 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.14.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.9.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect - github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect github.com/tdakkota/asciicheck v0.2.0 // indirect - github.com/tetafro/godot v1.4.16 // indirect + github.com/tetafro/godot v1.4.17 // indirect github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect github.com/timonwong/loggercheck v0.9.4 // indirect - github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect + github.com/tomarrell/wrapcheck/v2 v2.9.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.1.0 // indirect - github.com/ultraware/whitespace v0.1.0 // indirect - github.com/uudashr/gocognit v1.1.2 // indirect + github.com/ultraware/whitespace v0.1.1 // indirect + github.com/uudashr/gocognit v1.1.3 // indirect github.com/yagipy/maintidx v1.0.0 // indirect - github.com/yeya24/promlinter v0.2.0 // indirect - gitlab.com/bosi/decorder v0.4.1 // indirect + github.com/yeya24/promlinter v0.3.0 // indirect + gitlab.com/bosi/decorder v0.4.2 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect - golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848 // indirect - golang.org/x/mod v0.15.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.17.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect + golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/tools v0.24.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/protobuf v1.34.2 gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.4.6 // indirect - mvdan.cc/gofumpt v0.6.0 // indirect - mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect - mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 // indirect + honnef.co/go/tools v0.5.1 // indirect + mvdan.cc/gofumpt v0.7.0 // indirect + mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect ) replace github.com/google/licenseclassifier => github.com/google/licenseclassifier v0.0.0-20201113175434-78a70215ca36 require ( - github.com/4meepo/tagalign v1.3.3 // indirect - github.com/Antonboom/testifylint v1.1.1 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 // indirect + github.com/4meepo/tagalign v1.3.4 // indirect + github.com/Antonboom/testifylint v1.4.3 // indirect + github.com/Crocmagnon/fatcontext v0.5.2 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect github.com/alecthomas/go-check-sumtype v0.1.4 // indirect - github.com/alexkohler/nakedret/v2 v2.0.2 // indirect + github.com/alexkohler/nakedret/v2 v2.0.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/bombsimon/wsl/v4 v4.2.0 // indirect - github.com/butuzov/mirror v1.1.0 // indirect - github.com/catenacyber/perfsprint v0.6.0 // indirect - github.com/ccojocar/zxcvbn-go v1.0.1 // indirect - github.com/ghostiam/protogetter v0.3.4 // indirect - github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect + github.com/bombsimon/wsl/v4 v4.4.1 // indirect + github.com/butuzov/mirror v1.2.0 // indirect + github.com/catenacyber/perfsprint v0.7.1 // indirect + github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/ckaznocha/intrange v0.2.0 // indirect + github.com/ghostiam/protogetter v0.3.6 // indirect + github.com/go-viper/mapstructure/v2 v2.1.0 // indirect + github.com/golangci/modinfo v0.3.4 // indirect + github.com/golangci/plugin-module-register v0.1.1 // indirect github.com/google/licenseclassifier v0.0.0-20220326190949-7c62d6fe8d3a // indirect - github.com/jjti/go-spancheck v0.5.2 // indirect + github.com/jjti/go-spancheck v0.6.2 // indirect + github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect + github.com/lasiar/canonicalheader v1.1.1 // indirect github.com/macabu/inamedparam v0.1.3 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/urfave/cli/v2 v2.6.0 // indirect github.com/xen0n/gosmopolitan v1.2.2 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect - go-simpler.org/musttag v0.8.0 // indirect - go-simpler.org/sloglint v0.4.0 // indirect + go-simpler.org/musttag v0.12.2 // indirect + go-simpler.org/sloglint v0.7.2 // indirect + go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/goleak v1.2.1 // indirect ) diff --git a/go.sum b/go.sum index 650b475..0e0aa45 100644 --- a/go.sum +++ b/go.sum @@ -35,26 +35,28 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/4meepo/tagalign v1.3.3 h1:ZsOxcwGD/jP4U/aw7qeWu58i7dwYemfy5Y+IF1ACoNw= -github.com/4meepo/tagalign v1.3.3/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= -github.com/Abirdcfly/dupword v0.0.13 h1:SMS17YXypwP000fA7Lr+kfyBQyW14tTT+nRv9ASwUUo= -github.com/Abirdcfly/dupword v0.0.13/go.mod h1:Ut6Ue2KgF/kCOawpW4LnExT+xZLQviJPE4klBPMK/5Y= -github.com/Antonboom/errname v0.1.12 h1:oh9ak2zUtsLp5oaEd/erjB4GPu9w19NyoIskZClDcQY= -github.com/Antonboom/errname v0.1.12/go.mod h1:bK7todrzvlaZoQagP1orKzWXv59X/x0W0Io2XT1Ssro= -github.com/Antonboom/nilnil v0.1.7 h1:ofgL+BA7vlA1K2wNQOsHzLJ2Pw5B5DpWRLdDAVvvTow= -github.com/Antonboom/nilnil v0.1.7/go.mod h1:TP+ScQWVEq0eSIxqU8CbdT5DFWoHp0MbP+KMUO1BKYQ= -github.com/Antonboom/testifylint v1.1.1 h1:xCxYDNOBLImTKjBKPGtx1cHkTSywDAn76mYHTwH5lG8= -github.com/Antonboom/testifylint v1.1.1/go.mod h1:9PFi+vWa8zzl4/B/kqmFJcw85ZUv8ReyBzuQCd30+WI= +github.com/4meepo/tagalign v1.3.4 h1:P51VcvBnf04YkHzjfclN6BbsopfJR5rxs1n+5zHt+w8= +github.com/4meepo/tagalign v1.3.4/go.mod h1:M+pnkHH2vG8+qhE5bVc/zeP7HS/j910Fwa9TUSyZVI0= +github.com/Abirdcfly/dupword v0.1.1 h1:Bsxe0fIw6OwBtXMIncaTxCLHYO5BB+3mcsR5E8VXloY= +github.com/Abirdcfly/dupword v0.1.1/go.mod h1:B49AcJdTYYkpd4HjgAcutNGG9HZ2JWwKunH9Y2BA6sM= +github.com/Antonboom/errname v0.1.13 h1:JHICqsewj/fNckzrfVSe+T33svwQxmjC+1ntDsHOVvM= +github.com/Antonboom/errname v0.1.13/go.mod h1:uWyefRYRN54lBg6HseYCFhs6Qjcy41Y3Jl/dVhA87Ns= +github.com/Antonboom/nilnil v0.1.9 h1:eKFMejSxPSA9eLSensFmjW2XTgTwJMjZ8hUHtV4s/SQ= +github.com/Antonboom/nilnil v0.1.9/go.mod h1:iGe2rYwCq5/Me1khrysB4nwI7swQvjclR8/YRPl5ihQ= +github.com/Antonboom/testifylint v1.4.3 h1:ohMt6AHuHgttaQ1xb6SSnxCeK4/rnK7KKzbvs7DmEck= +github.com/Antonboom/testifylint v1.4.3/go.mod h1:+8Q9+AOLsz5ZiQiiYujJKs9mNz398+M6UgslP4qgJLA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Crocmagnon/fatcontext v0.5.2 h1:vhSEg8Gqng8awhPju2w7MKHqMlg4/NI+gSDHtR3xgwA= +github.com/Crocmagnon/fatcontext v0.5.2/go.mod h1:87XhRMaInHP44Q7Tlc7jkgKKB7kZAOPiDkFMdKCC+74= github.com/Djarvur/go-err113 v0.1.0 h1:uCRZZOdMQ0TZPHYTdYpoC0bLYJKPEHPUJ8MeAa51lNU= github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 h1:sATXp1x6/axKxz2Gjxv8MALP0bXaNRfQinEwyfMcx8c= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0/go.mod h1:Nl76DrGNJTA1KJ0LePKBw/vznBX1EHbAZX8mwjR82nI= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= @@ -68,8 +70,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexkohler/nakedret/v2 v2.0.2 h1:qnXuZNvv3/AxkAb22q/sEsEpcA99YxLFACDtEw9TPxE= -github.com/alexkohler/nakedret/v2 v2.0.2/go.mod h1:2b8Gkk0GsOrqQv/gPWjNLDSKwG8I5moSXG1K4VIBcTQ= +github.com/alexkohler/nakedret/v2 v2.0.4 h1:yZuKmjqGi0pSmjGpOC016LtPJysIL0WEUiaXW5SUnNg= +github.com/alexkohler/nakedret/v2 v2.0.4/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= @@ -92,25 +94,25 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bmatcuk/doublestar/v4 v4.0.2 h1:X0krlUVAVmtr2cRoTqR8aDMrDqnB36ht8wpWTiQ3jsA= github.com/bmatcuk/doublestar/v4 v4.0.2/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= -github.com/bombsimon/wsl/v4 v4.2.0 h1:dKK3o/Hk2aIt6t72CWg02ham2P5lnH9MBSW6cTU9xxU= -github.com/bombsimon/wsl/v4 v4.2.0/go.mod h1:1zaTbf/7ywOQtMdoUdTF2X1fbbBLiBUkajyuFAanT28= +github.com/bombsimon/wsl/v4 v4.4.1 h1:jfUaCkN+aUpobrMO24zwyAMwMAV5eSziCkOKEauOLdw= +github.com/bombsimon/wsl/v4 v4.4.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY= github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ= github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA= github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U= github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0= github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA= -github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= -github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= -github.com/catenacyber/perfsprint v0.6.0 h1:VSv95RRkk5+BxrU/YTPcnxuMEWar1iMK5Vyh3fWcBfs= -github.com/catenacyber/perfsprint v0.6.0/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= -github.com/ccojocar/zxcvbn-go v1.0.1 h1:+sxrANSCj6CdadkcMnvde/GWU1vZiiXRbqYSCalV4/4= -github.com/ccojocar/zxcvbn-go v1.0.1/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/butuzov/mirror v1.2.0 h1:9YVK1qIjNspaqWutSv8gsge2e/Xpq1eqEkslEUHy5cs= +github.com/butuzov/mirror v1.2.0/go.mod h1:DqZZDtzm42wIAIyHXeN8W/qb1EPlb9Qn/if9icBOpdQ= +github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc= +github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= +github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= +github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= @@ -118,45 +120,45 @@ github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+U github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/ckaznocha/intrange v0.2.0 h1:FykcZuJ8BD7oX93YbO1UY9oZtkRbp+1/kJcDjkefYLs= +github.com/ckaznocha/intrange v0.2.0/go.mod h1:r5I7nUlAAG56xmkOpw4XVr16BXhwYTUdcuRFeevn1oE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/daixiang0/gci v0.12.1 h1:ugsG+KRYny1VK4oqrX4Vtj70bo4akYKa0tgT1DXMYiY= -github.com/daixiang0/gci v0.12.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= +github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= +github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= -github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= +github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= +github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= -github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= -github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= +github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.4 h1:5SZ+lZSNmNkSbGVSF9hUHhv/b7ELF9Rwchoq7btYo6c= -github.com/ghostiam/protogetter v0.3.4/go.mod h1:A0JgIhs0fgVnotGinjQiKaFVG3waItLJNwPmcMzDnvk= -github.com/go-critic/go-critic v0.11.0 h1:mARtIFX7jPtJ3SzxO9Isa5T2jd2dZxFmQHK3yNf0wrE= -github.com/go-critic/go-critic v0.11.0/go.mod h1:Cz6lr1PlkIu/0Y0U9KqJgcIJJECAF8mEwmzVjKnhbfI= +github.com/ghostiam/protogetter v0.3.6 h1:R7qEWaSgFCsy20yYHNIJsU9ZOb8TziSRRxuAOTVKeOk= +github.com/ghostiam/protogetter v0.3.6/go.mod h1:7lpeDnEJ1ZjL/YtyoN99ljO4z0pd3H0d18/t2dPBxHw= +github.com/go-critic/go-critic v0.11.4 h1:O7kGOCx0NDIni4czrkRIXTnit0mkyKOCePh3My6OyEU= +github.com/go-critic/go-critic v0.11.4/go.mod h1:2QAdo4iuLik5S9YG0rT4wcZ8QxwHYkrr6/2MWAiv/vc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -168,19 +170,24 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= +github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= @@ -192,14 +199,14 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= -github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -232,26 +239,22 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= -github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= -github.com/golangci/golangci-lint v1.56.1 h1:vR6rJpjE1w6pRp2EkVeCAbISyUIl6c7OO/hrEtGK1yo= -github.com/golangci/golangci-lint v1.56.1/go.mod h1:sOHqnOxdEZ0u9JYrDuofOaIyO0jRgT8Y6nWfzuoSv0Y= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g= -github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI= -github.com/golangci/revgrep v0.5.2 h1:EndcWoRhcnfj2NHQ+28hyuXpLMF+dQmCN+YaeeIl4FU= -github.com/golangci/revgrep v0.5.2/go.mod h1:bjAMA+Sh/QUfTDcHzxfyHxr4xKvllVr/0sCv2e7jJHA= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 h1:/1322Qns6BtQxUZDTAT4SdcoxknUki7IAoK4SAXr8ME= +github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9/go.mod h1:Oesb/0uFAyWoaw1U1qS5zyjCg5NP9C9iwjnI4tIsXEE= +github.com/golangci/golangci-lint v1.61.0 h1:VvbOLaRVWmyxCnUIMTbf1kDsaJbTzH20FAMXTAlQGu8= +github.com/golangci/golangci-lint v1.61.0/go.mod h1:e4lztIrJJgLPhWvFPDkhiMwEFRrWlmFbrZea3FsJyN8= +github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= +github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= +github.com/golangci/modinfo v0.3.4 h1:oU5huX3fbxqQXdfspamej74DFX0kyGLkw1ppvXoJ8GA= +github.com/golangci/modinfo v0.3.4/go.mod h1:wytF1M5xl9u0ij8YSvhkEVPP3M5Mc7XLl1pxH3B2aUM= +github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= +github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/revgrep v0.5.3 h1:3tL7c1XBMtWHHqVpS5ChmiAAoe4PF/d5+ULzV9sLAzs= +github.com/golangci/revgrep v0.5.3/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= github.com/google/addlicense v1.1.1 h1:jpVf9qPbU8rz5MxKo7d+RMcNHkqxi4YJi/laauX4aAE= github.com/google/addlicense v1.1.1/go.mod h1:Sm/DHu7Jk+T5miFHHehdIjbi4M5+dJDRS3Cq0rncIxA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -282,8 +285,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -307,8 +310,8 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -317,17 +320,16 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.7.0 h1:cEqH+YBKLsECnRSd4F4TK5ri8t/aXtt/qoL0Ft252B0= -github.com/jgautheron/goconst v1.7.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= +github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jjti/go-spancheck v0.5.2 h1:WXTZG3efY/ji1Vi8mkH+23O3bLeKR6hp3tI3YB7XwKk= -github.com/jjti/go-spancheck v0.5.2/go.mod h1:ARPNI1JRG1V2Rjnd6/2f2NEfghjSVDZGVmruNKlnXU0= +github.com/jjti/go-spancheck v0.6.2 h1:iYtoxqPMzHUPp7St+5yA8+cONdyXD3ug6KK15n7Pklk= +github.com/jjti/go-spancheck v0.6.2/go.mod h1:+X7lvIrR5ZdUTkxFYqzJ0abr8Sb5LOo80uOhWNqIrYA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -339,12 +341,13 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/karamaru-alpha/copyloopvar v1.1.0 h1:x7gNyKcC2vRBO1H2Mks5u1VxQtYvFiym7fCjIP8RPos= +github.com/karamaru-alpha/copyloopvar v1.1.0/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k= github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0= github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= -github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= +github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg= +github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -357,16 +360,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.9 h1:3Sr2IfFNcsMmlqPk1cjTUbJ4zofKPGyHxenwPebgTug= -github.com/kunwardeep/paralleltest v1.0.9/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= +github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= -github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= -github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/lasiar/canonicalheader v1.1.1 h1:wC+dY9ZfiqiPwAexUApFush/csSPXeIi4QqyxXmng8I= +github.com/lasiar/canonicalheader v1.1.1/go.mod h1:cXkb3Dlk6XXy+8MVQnF23CYKWlyA7kfQhSw2CcZtZb0= +github.com/ldez/gomoddirectives v0.2.4 h1:j3YjBIjEBbqZ0NKtBNzr8rtMHTOrLPeiwTkfUJZ3alg= +github.com/ldez/gomoddirectives v0.2.4/go.mod h1:oWu9i62VcQDYp9EQ0ONTfqLNh+mDLWWDO+SO0qSQw5g= github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= -github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= -github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= +github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= +github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= @@ -394,10 +399,8 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= -github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE= -github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA= +github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A= +github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU= github.com/missionMeteora/toolkit v0.0.0-20170713173850-88364e3ef8cc h1:/oFlKiuu6L1sIvZ7A363qMhNM+DUQL5WsVe1xIRQnFU= github.com/missionMeteora/toolkit v0.0.0-20170713173850-88364e3ef8cc/go.mod h1:AtX+JBtXbQ+taj82QFzCSgN5EzM4Bi0YRyS+TVbjENs= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -409,8 +412,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= -github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= +github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= +github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -425,8 +428,8 @@ github.com/nitrictech/nitric/core v0.0.0-20240501153359-997c6077b84f h1:usgb/sRq github.com/nitrictech/nitric/core v0.0.0-20240501153359-997c6077b84f/go.mod h1:OfaIrPrJJjrFNOOgYbzoBGUblO2DadoXCrloAsUW0H0= github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf h1:8MB8W8ylM8sCM2COGfiO39/tB6BTdiawLszaUGCNL5w= github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf/go.mod h1:b2lzk2a4o1bvSrSCE6yvTldHuXCJymuDVhdMJGOSslw= -github.com/nunnatsa/ginkgolinter v0.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1oBKBNHg= -github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc= +github.com/nunnatsa/ginkgolinter v0.16.2 h1:8iLqHIZvN4fTLDC0Ke9tbSZVcyVHoBs0HIbnVSxfHJk= +github.com/nunnatsa/ginkgolinter v0.16.2/go.mod h1:4tWRinDN1FeJgU+iJANW/kz7xKN5nYRAOfJDQUS9dOQ= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -436,12 +439,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= +github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= -github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -451,8 +454,8 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -460,8 +463,10 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.4.8 h1:jiEjKDH33ouFktyez7sckv6pHWif9B7SuS8cutDXFHw= -github.com/polyfloyd/go-errorlint v1.4.8/go.mod h1:NNCxFcFjZcw3xNjVdCchERkEM6Oz7wta2XJVxRftwO4= +github.com/polyfloyd/go-errorlint v1.6.0 h1:tftWV9DE7txiFzPpztTAwyoRLKNj9gpVm2cg8/OwcYY= +github.com/polyfloyd/go-errorlint v1.6.0/go.mod h1:HR7u8wuP1kb1NeN1zqTd1ZMlqUKPPHF+Id4vIPvDqVw= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -488,8 +493,10 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/quasilyte/go-ruleguard v0.4.0 h1:DyM6r+TKL+xbKB4Nm7Afd1IQh9kEUKQs2pboWGKtvQo= -github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= +github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= +github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= +github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= @@ -504,18 +511,20 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= -github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= +github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= +github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.24.0 h1:MKNzmXtGh5N0y74Z/CIaJh4GlB364l0K1RUT08WSWAc= -github.com/sashamelentyev/usestdlibvars v1.24.0/go.mod h1:9cYkq+gYJ+a5W2RPdhfaSCnTVUC1OQP/bSiiBhq3OZE= -github.com/securego/gosec/v2 v2.18.2 h1:DkDt3wCiOtAHf1XkiXZBhQ6m6mK/b9T/wD257R3/c+I= -github.com/securego/gosec/v2 v2.18.2/go.mod h1:xUuqSF6i0So56Y2wwohWAmB07EdBkUN6crbLlHwbyJs= +github.com/sashamelentyev/usestdlibvars v1.27.0 h1:t/3jZpSXtRPRf2xr0m63i32ZrusyurIGT9E5wAvXQnI= +github.com/sashamelentyev/usestdlibvars v1.27.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/securego/gosec/v2 v2.21.2 h1:deZp5zmYf3TWwU7A7cR2+SolbTpZ3HQiwFqnzQyEl3M= +github.com/securego/gosec/v2 v2.21.2/go.mod h1:au33kg78rNseF5PwPnTWhuYBFf534bvJRvOrgZ/bFzU= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= @@ -530,10 +539,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= -github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= -github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/sivchari/tenv v1.10.0 h1:g/hzMA+dBCKqGXgW8AV/1xIWhAvDrx0zFKNR48NFMg0= +github.com/sivchari/tenv v1.10.0/go.mod h1:tdY24masnVoZFxYrHv/nD6Tc8FbkEtAQEEziXpyMgqY= github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= @@ -542,8 +549,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -557,8 +564,9 @@ github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8L github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -567,44 +575,43 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.16 h1:4ChfhveiNLk4NveAZ9Pu2AN8QZ2nkUGFuadM9lrr5D0= -github.com/tetafro/godot v1.4.16/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/tetafro/godot v1.4.17 h1:pGzu+Ye7ZUEFx7LHU0dAKmCOXWsPjl7qA6iMGndsjPs= +github.com/tetafro/godot v1.4.17/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= -github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= -github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= +github.com/tomarrell/wrapcheck/v2 v2.9.0 h1:801U2YCAjLhdN8zhZ/7tdjB3EnAoRlJHt/s+9hijLQ4= +github.com/tomarrell/wrapcheck/v2 v2.9.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= -github.com/ultraware/whitespace v0.1.0 h1:O1HKYoh0kIeqE8sFqZf1o0qbORXUCOQFrlaQyZsczZw= -github.com/ultraware/whitespace v0.1.0/go.mod h1:/se4r3beMFNmewJ4Xmz0nMQ941GJt+qmSHGP9emHYe0= +github.com/ultraware/whitespace v0.1.1 h1:bTPOGejYFulW3PkcrqkeQwOd6NKOOXvmGD9bo/Gk8VQ= +github.com/ultraware/whitespace v0.1.1/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/urfave/cli/v2 v2.6.0 h1:yj2Drkflh8X/zUrkWlWlUjZYHyWN7WMmpVxyxXIUyv8= github.com/urfave/cli/v2 v2.6.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= -github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= -github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= +github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM= +github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U= github.com/uw-labs/lichen v0.1.7 h1:SDNE3kThhhtP70XfLN/C2bqaT9Epefg1i10lhWYIG4g= github.com/uw-labs/lichen v0.1.7/go.mod h1:bvEgoBeVZGhzstRxPEpEwM4TGT6AJZ6GA29a4FuLxYw= github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= -github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= -github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= +github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= +github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4= github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -614,14 +621,14 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4= -gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA= -go-simpler.org/assert v0.7.0 h1:OzWWZqfNxt8cLS+MlUp6Tgk1HjPkmgdKBq9qvy8lZsA= -go-simpler.org/assert v0.7.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.8.0 h1:DR4UTgetNNhPRNo02rkK1hwDTRzAPotN+ZqYpdtEwWc= -go-simpler.org/musttag v0.8.0/go.mod h1:fiNdCkXt2S6je9Eblma3okjnlva9NT1Eg/WUt19rWu8= -go-simpler.org/sloglint v0.4.0 h1:UVJuUJo63iNQNFEOtZ6o1xAgagVg/giVLLvG9nNLobI= -go-simpler.org/sloglint v0.4.0/go.mod h1:v6zJ++j/thFPhefs2wEXoCKwT10yo5nkBDYRCXyqgNQ= +gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= +gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= +go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= +go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= +go-simpler.org/musttag v0.12.2 h1:J7lRc2ysXOq7eM8rwaTYnNrHd5JwjppzB6mScysB2Cs= +go-simpler.org/musttag v0.12.2/go.mod h1:uN1DVIasMTQKk6XSik7yrJoEysGtR2GRqvWnI9S7TYM= +go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY= +go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -630,6 +637,8 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= +go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= @@ -654,12 +663,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk= +golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848 h1:UhRVJ0i7bF9n/Hd8YjW3eKjlPVBHzbQdxrBgjbSKl64= -golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8= +golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -688,8 +697,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -732,8 +741,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -754,8 +763,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -806,7 +815,6 @@ golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -816,8 +824,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -834,8 +842,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -886,7 +894,6 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= @@ -897,14 +904,13 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -960,8 +966,8 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -974,8 +980,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 h1:TLkBREm4nIsEcexnCjgQd5GQWaHcqMzwQV0TX9pq8S0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -991,8 +997,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1023,16 +1029,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8= -honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= -mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= -mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 h1:zCr3iRRgdk5eIikZNDphGcM6KGVTx3Yu+/Uu9Es254w= -mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14/go.mod h1:ZzZjEpJDOmx8TdVU6umamY3Xy0UAQUI2DHbf05USVbI= +honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= +honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= +mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= +mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= +mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= +mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/licenses.go b/licenses.go index 1265924..9c01561 100644 --- a/licenses.go +++ b/licenses.go @@ -24,7 +24,6 @@ import ( _ "github.com/nitrictech/go-sdk/api/storage" _ "github.com/nitrictech/go-sdk/api/topics" _ "github.com/nitrictech/go-sdk/nitric" - _ "github.com/nitrictech/go-sdk/workers" ) func main() {} diff --git a/nitric/api.go b/nitric/api.go index 73c6b80..48c7cd6 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -119,31 +119,31 @@ func (r *route) AddMethodHandler(methods []string, middleware Middleware[httpx.C } func (r *route) All(handler Middleware[httpx.Ctx], opts ...MethodOption) { - r.AddMethodHandler([]string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions}, handler, opts...) + _ = r.AddMethodHandler([]string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions}, handler, opts...) } func (r *route) Get(handler Middleware[httpx.Ctx], opts ...MethodOption) { - r.AddMethodHandler([]string{http.MethodGet}, handler, opts...) + _ = r.AddMethodHandler([]string{http.MethodGet}, handler, opts...) } func (r *route) Post(handler Middleware[httpx.Ctx], opts ...MethodOption) { - r.AddMethodHandler([]string{http.MethodPost}, handler, opts...) + _ = r.AddMethodHandler([]string{http.MethodPost}, handler, opts...) } func (r *route) Put(handler Middleware[httpx.Ctx], opts ...MethodOption) { - r.AddMethodHandler([]string{http.MethodPut}, handler, opts...) + _ = r.AddMethodHandler([]string{http.MethodPut}, handler, opts...) } func (r *route) Patch(handler Middleware[httpx.Ctx], opts ...MethodOption) { - r.AddMethodHandler([]string{http.MethodPatch}, handler, opts...) + _ = r.AddMethodHandler([]string{http.MethodPatch}, handler, opts...) } func (r *route) Delete(handler Middleware[httpx.Ctx], opts ...MethodOption) { - r.AddMethodHandler([]string{http.MethodDelete}, handler, opts...) + _ = r.AddMethodHandler([]string{http.MethodDelete}, handler, opts...) } func (r *route) Options(handler Middleware[httpx.Ctx], opts ...MethodOption) { - r.AddMethodHandler([]string{http.MethodOptions}, handler, opts...) + _ = r.AddMethodHandler([]string{http.MethodOptions}, handler, opts...) } // Api Resource represents an HTTP API, capable of routing and securing incoming HTTP requests to handlers. @@ -196,7 +196,10 @@ func NewApi(name string, opts ...ApiOption) (Api, error) { // Attaching OIDC Options to API if a.security != nil { for _, oidcOption := range a.security { - attachOidc(a.name, oidcOption) + err := attachOidc(a.name, oidcOption) + if err != nil { + return nil, err + } if apiResource.GetSecurity() == nil { apiResource.Security = make(map[string]*resourcev1.ApiScopes) diff --git a/nitric/api_workers.go b/nitric/api_workers.go index 8183bac..f58e500 100644 --- a/nitric/api_workers.go +++ b/nitric/api_workers.go @@ -16,6 +16,7 @@ package nitric import ( "context" + errorsstd "errors" "fmt" "io" @@ -64,7 +65,7 @@ func (a *apiWorker) Start(ctx context.Context) error { resp, err := stream.Recv() - if err == io.EOF { + if errorsstd.Is(err, io.EOF) { err = stream.CloseSend() if err != nil { return err @@ -93,13 +94,7 @@ func (a *apiWorker) Start(ctx context.Context) error { } func newApiWorker(opts *apiWorkerOpts) *apiWorker { - ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/bucket_workers.go b/nitric/bucket_workers.go index 50b226e..703b4af 100644 --- a/nitric/bucket_workers.go +++ b/nitric/bucket_workers.go @@ -16,6 +16,7 @@ package nitric import ( "context" + errorsstd "errors" "fmt" "io" @@ -61,7 +62,7 @@ func (b *bucketEventWorker) Start(ctx context.Context) error { resp, err := stream.Recv() - if err == io.EOF { + if errorsstd.Is(err, io.EOF) { err = stream.CloseSend() if err != nil { return err @@ -89,13 +90,7 @@ func (b *bucketEventWorker) Start(ctx context.Context) error { } func newBucketEventWorker(opts *bucketEventWorkerOpts) *bucketEventWorker { - ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/manager.go b/nitric/manager.go index d594600..e8dd831 100644 --- a/nitric/manager.go +++ b/nitric/manager.go @@ -82,13 +82,7 @@ func (m *manager) resourceServiceClient() (v1.ResourcesClient, error) { defer m.connMutex.Unlock() if m.conn == nil { - ctx, _ := context.WithTimeout(context.Background(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { return nil, err } diff --git a/nitric/middleware.go b/nitric/middleware.go index c80332d..a1af518 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -1,9 +1,25 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 nitric import "fmt" -type Handler[T any] func(context *T) (*T, error) -type Middleware[T any] func(context *T, next Handler[T]) (*T, error) +type ( + Handler[T any] func(context *T) (*T, error) + Middleware[T any] func(context *T, next Handler[T]) (*T, error) +) type chainedMiddleware[T any] struct { fun Middleware[T] diff --git a/nitric/schedule_workers.go b/nitric/schedule_workers.go index 9267391..541d1af 100644 --- a/nitric/schedule_workers.go +++ b/nitric/schedule_workers.go @@ -16,6 +16,7 @@ package nitric import ( "context" + errorsstd "errors" "fmt" "io" @@ -61,7 +62,7 @@ func (i *scheduleWorker) Start(ctx context.Context) error { resp, err := stream.Recv() - if err == io.EOF { + if errorsstd.Is(err, io.EOF) { err = stream.CloseSend() if err != nil { return err @@ -89,13 +90,7 @@ func (i *scheduleWorker) Start(ctx context.Context) error { } func newScheduleWorker(opts *scheduleWorkerOpts) *scheduleWorker { - ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/topic_workers.go b/nitric/topic_workers.go index c4e8c49..d929c5d 100644 --- a/nitric/topic_workers.go +++ b/nitric/topic_workers.go @@ -21,6 +21,8 @@ import ( "google.golang.org/grpc" + errorsstd "errors" + "github.com/nitrictech/go-sdk/api/errors" "github.com/nitrictech/go-sdk/api/errors/codes" "github.com/nitrictech/go-sdk/api/topics" @@ -61,7 +63,7 @@ func (s *subscriptionWorker) Start(ctx context.Context) error { resp, err := stream.Recv() - if err == io.EOF { + if errorsstd.Is(err, io.EOF) { err = stream.CloseSend() if err != nil { return err @@ -89,13 +91,7 @@ func (s *subscriptionWorker) Start(ctx context.Context) error { } func newSubscriptionWorker(opts *subscriptionWorkerOpts) *subscriptionWorker { - ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/websocket_workers.go b/nitric/websocket_workers.go index 1b7c834..cff03dd 100644 --- a/nitric/websocket_workers.go +++ b/nitric/websocket_workers.go @@ -16,6 +16,7 @@ package nitric import ( "context" + errorsstd "errors" "fmt" "io" @@ -61,7 +62,7 @@ func (w *websocketWorker) Start(ctx context.Context) error { resp, err := stream.Recv() - if err == io.EOF { + if errorsstd.Is(err, io.EOF) { err = stream.CloseSend() if err != nil { return err @@ -89,13 +90,7 @@ func (w *websocketWorker) Start(ctx context.Context) error { } func newWebsocketWorker(opts *websocketWorkerOpts) *websocketWorker { - ctx, _ := context.WithTimeout(context.TODO(), constants.NitricDialTimeout()) - - conn, err := grpc.DialContext( - ctx, - constants.NitricAddress(), - constants.DefaultOptions()..., - ) + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/workers/file_event.go b/workers/file_event.go deleted file mode 100644 index 2b54975..0000000 --- a/workers/file_event.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2023 Nitric Technologies Pty Ltd. -// -// 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 workers From 1839ebef0d50e40349837fba6b88582b6eb0069b Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 15:59:58 +1000 Subject: [PATCH 05/42] accept interface. --- nitric/api.go | 11 ++++++++--- nitric/middleware.go | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/nitric/api.go b/nitric/api.go index 48c7cd6..bc8e55b 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -152,7 +152,7 @@ func (r *route) Options(handler Middleware[httpx.Ctx], opts ...MethodOption) { // // Note: to chain middleware use handler.ComposeHttpMiddlware() type Api interface { - Get(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + Get(path string, handler interface{}, opts ...MethodOption) Put(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) Patch(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) Post(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) @@ -228,10 +228,15 @@ func NewApi(name string, opts ...ApiOption) (Api, error) { // Get adds a Get method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Get(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (a *api) Get(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) - r.Get(handler, opts...) + mw, err := interfaceToMiddleware[httpx.Ctx](handler) + if err != nil { + panic(err) + } + + r.Get(mw, opts...) a.routes[match] = r } diff --git a/nitric/middleware.go b/nitric/middleware.go index a1af518..8d4cdf4 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -30,6 +30,30 @@ func dummyHandler[T any](ctx *T) (*T, error) { return ctx, nil } +func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { + var handlerType Middleware[T] + switch typ := mw.(type) { + case Middleware[T]: + handlerType = typ + case Handler[T]: + handlerType = handlerToMware(typ) + default: + return nil, fmt.Errorf("invalid middleware type: %T", mw) + } + + return handlerType, nil +} + +func handlerToMware[T any](h Handler[T]) Middleware[T] { + return func(ctx *T, next Handler[T]) (*T, error) { + ctx, err := h(ctx) + if err != nil { + return next(ctx) + } + return nil, err + } +} + func (c *chainedMiddleware[T]) invoke(ctx *T) (*T, error) { // Chains are left open-ended so middleware can continue to be linked // If the chain is incomplete, set a chained dummy handler for safety From 5d7753dd75bcbf6a65eb218750f3dc28c0c449fa Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 16:13:58 +1000 Subject: [PATCH 06/42] handle interface conversion. --- nitric/middleware.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nitric/middleware.go b/nitric/middleware.go index 8d4cdf4..a574036 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -33,9 +33,9 @@ func dummyHandler[T any](ctx *T) (*T, error) { func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { var handlerType Middleware[T] switch typ := mw.(type) { - case Middleware[T]: - handlerType = typ - case Handler[T]: + case func(*T, Handler[T]) (*T, error): + handlerType = Middleware[T](typ) + case func(*T) (*T, error): handlerType = handlerToMware(typ) default: return nil, fmt.Errorf("invalid middleware type: %T", mw) From fd2cd57a417cebe9d73353aa3fbc434565f7b74b Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 16:21:01 +1000 Subject: [PATCH 07/42] fix logic error. --- nitric/middleware.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nitric/middleware.go b/nitric/middleware.go index a574036..93bec70 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -47,7 +47,7 @@ func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { func handlerToMware[T any](h Handler[T]) Middleware[T] { return func(ctx *T, next Handler[T]) (*T, error) { ctx, err := h(ctx) - if err != nil { + if err == nil { return next(ctx) } return nil, err From 7cb17712343eb80b4058542b3bf2264191f5f11e Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 16:28:38 +1000 Subject: [PATCH 08/42] broaden what middleware can be. --- nitric/middleware.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nitric/middleware.go b/nitric/middleware.go index 93bec70..4ce8879 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -33,10 +33,23 @@ func dummyHandler[T any](ctx *T) (*T, error) { func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { var handlerType Middleware[T] switch typ := mw.(type) { + case Middleware[T]: + handlerType = typ case func(*T, Handler[T]) (*T, error): handlerType = Middleware[T](typ) + case Handler[T]: + handlerType = handlerToMware(typ) case func(*T) (*T, error): handlerType = handlerToMware(typ) + case func(*T) *T: + handlerType = handlerToMware(func(ctx *T) (*T, error) { + return typ(ctx), nil + }) + case func(*T): + handlerType = handlerToMware(func(ctx *T) (*T, error) { + typ(ctx) + return ctx, nil + }) default: return nil, fmt.Errorf("invalid middleware type: %T", mw) } From 70f9f5c784c45a215499d94c39290c69286728c8 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 17:18:44 +1000 Subject: [PATCH 09/42] broaden the api interface. --- api/{http => apis}/context.go | 2 +- api/{http => apis}/request.go | 2 +- api/{http => apis}/response.go | 2 +- nitric/api.go | 140 ++++++++++++++++++++++++++------- nitric/api_workers.go | 2 +- nitric/middleware.go | 72 ++++++++++++++--- nitric/options.go | 4 +- 7 files changed, 178 insertions(+), 46 deletions(-) rename api/{http => apis}/context.go (99%) rename api/{http => apis}/request.go (99%) rename api/{http => apis}/response.go (98%) diff --git a/api/http/context.go b/api/apis/context.go similarity index 99% rename from api/http/context.go rename to api/apis/context.go index 04a992b..ecaef24 100644 --- a/api/http/context.go +++ b/api/apis/context.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package http +package apis import apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" diff --git a/api/http/request.go b/api/apis/request.go similarity index 99% rename from api/http/request.go rename to api/apis/request.go index 7060169..500c601 100644 --- a/api/http/request.go +++ b/api/apis/request.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package http +package apis type Request interface { Method() string diff --git a/api/http/response.go b/api/apis/response.go similarity index 98% rename from api/http/response.go rename to api/apis/response.go index 0b517da..9ddc028 100644 --- a/api/http/response.go +++ b/api/apis/response.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package http +package apis type Response struct { Status int diff --git a/nitric/api.go b/nitric/api.go index bc8e55b..536d2bf 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -19,7 +19,7 @@ import ( "path" "strings" - httpx "github.com/nitrictech/go-sdk/api/http" + httpx "github.com/nitrictech/go-sdk/api/apis" apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" resourcev1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" @@ -27,13 +27,13 @@ import ( // Route providers convenience functions to register a handler in a single method. type Route interface { - All(handler Middleware[httpx.Ctx], opts ...MethodOption) - Get(handler Middleware[httpx.Ctx], opts ...MethodOption) - Patch(handler Middleware[httpx.Ctx], opts ...MethodOption) - Put(handler Middleware[httpx.Ctx], opts ...MethodOption) - Post(handler Middleware[httpx.Ctx], opts ...MethodOption) - Delete(handler Middleware[httpx.Ctx], opts ...MethodOption) - Options(handler Middleware[httpx.Ctx], opts ...MethodOption) + All(handler interface{}, opts ...MethodOption) + Get(handler interface{}, opts ...MethodOption) + Patch(handler interface{}, opts ...MethodOption) + Put(handler interface{}, opts ...MethodOption) + Post(handler interface{}, opts ...MethodOption) + Delete(handler interface{}, opts ...MethodOption) + Options(handler interface{}, opts ...MethodOption) ApiName() string } @@ -68,7 +68,7 @@ func (r *route) ApiName() string { return r.api.name } -func (r *route) AddMethodHandler(methods []string, middleware Middleware[httpx.Ctx], opts ...MethodOption) error { +func (r *route) AddMethodHandler(methods []string, middleware interface{}, opts ...MethodOption) error { bName := path.Join(r.api.name, r.path, strings.Join(methods, "-")) // default methodOptions will contain OidcOptions passed to API instance and securityDisabled to false @@ -81,7 +81,12 @@ func (r *route) AddMethodHandler(methods []string, middleware Middleware[httpx.C o(mo) } - composedHandler := Compose(r.middleware, middleware) + mw, err := interfaceToMiddleware[httpx.Ctx](middleware) + if err != nil { + panic(err) + } + + composedHandler := Compose(r.middleware, mw) apiOpts := &apispb.ApiWorkerOptions{ SecurityDisabled: mo.securityDisabled, @@ -118,31 +123,31 @@ func (r *route) AddMethodHandler(methods []string, middleware Middleware[httpx.C return nil } -func (r *route) All(handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (r *route) All(handler interface{}, opts ...MethodOption) { _ = r.AddMethodHandler([]string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions}, handler, opts...) } -func (r *route) Get(handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (r *route) Get(handler interface{}, opts ...MethodOption) { _ = r.AddMethodHandler([]string{http.MethodGet}, handler, opts...) } -func (r *route) Post(handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (r *route) Post(handler interface{}, opts ...MethodOption) { _ = r.AddMethodHandler([]string{http.MethodPost}, handler, opts...) } -func (r *route) Put(handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (r *route) Put(handler interface{}, opts ...MethodOption) { _ = r.AddMethodHandler([]string{http.MethodPut}, handler, opts...) } -func (r *route) Patch(handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (r *route) Patch(handler interface{}, opts ...MethodOption) { _ = r.AddMethodHandler([]string{http.MethodPatch}, handler, opts...) } -func (r *route) Delete(handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (r *route) Delete(handler interface{}, opts ...MethodOption) { _ = r.AddMethodHandler([]string{http.MethodDelete}, handler, opts...) } -func (r *route) Options(handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (r *route) Options(handler interface{}, opts ...MethodOption) { _ = r.AddMethodHandler([]string{http.MethodOptions}, handler, opts...) } @@ -152,12 +157,96 @@ func (r *route) Options(handler Middleware[httpx.Ctx], opts ...MethodOption) { // // Note: to chain middleware use handler.ComposeHttpMiddlware() type Api interface { + // Get adds a Get method handler to the path with any specified opts. + // Valid function signatures: + // + // func() + // func() error + // func(*apis.Context) + // func(*apis.Context) error + // func(*apis.Context) *apis.Context + // func(*apis.Context) (*apis.Context, error) + // func(*apis.Context, Handler[apis.Context]) *apis.Context + // func(*apis.Context, Handler[apis.Context]) error + // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) + // Middleware[apis.Context] + // Handler[apis.Context] Get(path string, handler interface{}, opts ...MethodOption) - Put(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) - Patch(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) - Post(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) - Delete(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) - Options(path string, handler Middleware[httpx.Ctx], opts ...MethodOption) + // Put adds a Put method handler to the path with any specified opts. + // Valid function signatures: + // + // func() + // func() error + // func(*apis.Context) + // func(*apis.Context) error + // func(*apis.Context) *apis.Context + // func(*apis.Context) (*apis.Context, error) + // func(*apis.Context, Handler[apis.Context]) *apis.Context + // func(*apis.Context, Handler[apis.Context]) error + // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) + // Middleware[apis.Context] + // Handler[apis.Context] + Put(path string, handler interface{}, opts ...MethodOption) + // Patch adds a Patch method handler to the path with any specified opts. + // Valid function signatures: + // + // func() + // func() error + // func(*apis.Context) + // func(*apis.Context) error + // func(*apis.Context) *apis.Context + // func(*apis.Context) (*apis.Context, error) + // func(*apis.Context, Handler[apis.Context]) *apis.Context + // func(*apis.Context, Handler[apis.Context]) error + // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) + // Middleware[apis.Context] + // Handler[apis.Context] + Patch(path string, handler interface{}, opts ...MethodOption) + // Post adds a Post method handler to the path with any specified opts. + // Valid function signatures: + // + // func() + // func() error + // func(*apis.Context) + // func(*apis.Context) error + // func(*apis.Context) *apis.Context + // func(*apis.Context) (*apis.Context, error) + // func(*apis.Context, Handler[apis.Context]) *apis.Context + // func(*apis.Context, Handler[apis.Context]) error + // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) + // Middleware[apis.Context] + // Handler[apis.Context] + Post(path string, handler interface{}, opts ...MethodOption) + // Delete adds a Delete method handler to the path with any specified opts. + // Valid function signatures: + // + // func() + // func() error + // func(*apis.Context) + // func(*apis.Context) error + // func(*apis.Context) *apis.Context + // func(*apis.Context) (*apis.Context, error) + // func(*apis.Context, Handler[apis.Context]) *apis.Context + // func(*apis.Context, Handler[apis.Context]) error + // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) + // Middleware[apis.Context] + // Handler[apis.Context] + Delete(path string, handler interface{}, opts ...MethodOption) + // Options adds a Options method handler to the path with any specified opts. + // Valid function signatures: + // + // func() + // func() error + // func(*apis.Context) + // func(*apis.Context) error + // func(*apis.Context) *apis.Context + // func(*apis.Context) (*apis.Context, error) + // func(*apis.Context, Handler[apis.Context]) *apis.Context + // func(*apis.Context, Handler[apis.Context]) error + // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) + // Middleware[apis.Context] + // Handler[apis.Context] + Options(path string, handler interface{}, opts ...MethodOption) NewRoute(path string, middleware ...Middleware[httpx.Ctx]) Route } @@ -231,12 +320,7 @@ func NewApi(name string, opts ...ApiOption) (Api, error) { func (a *api) Get(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) - mw, err := interfaceToMiddleware[httpx.Ctx](handler) - if err != nil { - panic(err) - } - - r.Get(mw, opts...) + r.Get(handler, opts...) a.routes[match] = r } diff --git a/nitric/api_workers.go b/nitric/api_workers.go index f58e500..be99df4 100644 --- a/nitric/api_workers.go +++ b/nitric/api_workers.go @@ -22,9 +22,9 @@ import ( "google.golang.org/grpc" + httpx "github.com/nitrictech/go-sdk/api/apis" "github.com/nitrictech/go-sdk/api/errors" "github.com/nitrictech/go-sdk/api/errors/codes" - httpx "github.com/nitrictech/go-sdk/api/http" "github.com/nitrictech/go-sdk/constants" v1 "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" ) diff --git a/nitric/middleware.go b/nitric/middleware.go index 4ce8879..339d4db 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -30,26 +30,74 @@ func dummyHandler[T any](ctx *T) (*T, error) { return ctx, nil } +// interfaceToMiddleware - Converts a function to a Middleware +// Valid function types are: +// func() +// func() error +// func(*T) +// func(*T) error +// func(*T) *T +// func(*T) (*T, error) +// func(*T, Handler[T]) *T +// func(*T, Handler[T]) error +// func(*T, Handler[T]) (*T, error) +// Middleware[T] +// Handler[T] +// If the function is not a valid type, an error is returned func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { var handlerType Middleware[T] switch typ := mw.(type) { - case Middleware[T]: - handlerType = typ - case func(*T, Handler[T]) (*T, error): - handlerType = Middleware[T](typ) - case Handler[T]: - handlerType = handlerToMware(typ) - case func(*T) (*T, error): - handlerType = handlerToMware(typ) - case func(*T) *T: - handlerType = handlerToMware(func(ctx *T) (*T, error) { - return typ(ctx), nil - }) + case func(): + handlerType = func(ctx *T, next Handler[T]) (*T, error) { + typ() + return next(ctx) + } + case func() error: + handlerType = func(ctx *T, next Handler[T]) (*T, error) { + err := typ() + if err != nil { + return nil, err + } + return next(ctx) + } case func(*T): handlerType = handlerToMware(func(ctx *T) (*T, error) { typ(ctx) return ctx, nil }) + case func(*T) error: + handlerType = handlerToMware(func(ctx *T) (*T, error) { + err := typ(ctx) + if err != nil { + return nil, err + } + return ctx, nil + }) + case func(*T) *T: + handlerType = handlerToMware(func(ctx *T) (*T, error) { + return typ(ctx), nil + }) + case func(*T) (*T, error): + handlerType = handlerToMware(typ) + case func(*T, Handler[T]) *T: + handlerType = Middleware[T](func(ctx *T, next Handler[T]) (*T, error) { + return typ(ctx, next), nil + }) + case func(*T, Handler[T]) error: + handlerType = Middleware[T](func(ctx *T, next Handler[T]) (*T, error) { + err := typ(ctx, next) + if err != nil { + return nil, err + } + return next(ctx) + }) + case func(*T, Handler[T]) (*T, error): + handlerType = Middleware[T](typ) + case Middleware[T]: + handlerType = typ + case Handler[T]: + handlerType = handlerToMware(typ) + default: return nil, fmt.Errorf("invalid middleware type: %T", mw) } diff --git a/nitric/options.go b/nitric/options.go index 787851d..35b66c3 100644 --- a/nitric/options.go +++ b/nitric/options.go @@ -15,7 +15,7 @@ package nitric import ( - "github.com/nitrictech/go-sdk/api/http" + "github.com/nitrictech/go-sdk/api/apis" ) type ( @@ -44,7 +44,7 @@ func OidcRule(name string, issuer string, audiences []string) SecurityOption { } } -func WithMiddleware(middleware ...Middleware[http.Ctx]) ApiOption { +func WithMiddleware(middleware ...Middleware[apis.Ctx]) ApiOption { return func(api *api) { if api.middleware != nil { api.middleware = Compose(api.middleware, Compose(middleware...)) From 8504b2af0a46d683fc27a6d32d3d0015f1b79f4e Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 17:51:03 +1000 Subject: [PATCH 10/42] flexible middleware --- api/keyvalue/keyvalue_test.go | 27 ------- api/queues/queues_test.go | 27 ------- api/secrets/secrets_test.go | 27 ------- api/storage/storage_test.go | 28 ------- api/topics/topics_test.go | 28 ------- nitric/api.go | 118 +++++++++++++++--------------- nitric/bucket.go | 26 ++++++- nitric/middleware.go | 12 +++ nitric/middleware_test.go | 129 +++++++++++++++++++++++++++++++++ nitric/resources_suite_test.go | 18 ++--- nitric/schedule.go | 57 ++++++++++++--- nitric/topic.go | 25 ++++++- nitric/websocket.go | 14 ++++ 13 files changed, 315 insertions(+), 221 deletions(-) create mode 100644 nitric/middleware_test.go diff --git a/api/keyvalue/keyvalue_test.go b/api/keyvalue/keyvalue_test.go index fe36b68..4134b3c 100644 --- a/api/keyvalue/keyvalue_test.go +++ b/api/keyvalue/keyvalue_test.go @@ -15,8 +15,6 @@ package keyvalue import ( - "os" - "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -68,31 +66,6 @@ var _ = Describe("KeyValue API", func() { }) }) }) - - Describe("New method", func() { - When("constructing a new queue client without the membrane", func() { - BeforeEach(func() { - os.Setenv("NITRIC_SERVICE_DIAL_TIMEOUT", "10") - }) - AfterEach(func() { - os.Unsetenv("NITRIC_SERVICE_DIAL_TIMEOUT") - }) - - c, err := New() - - It("should return a nil client", func() { - Expect(c).To(BeNil()) - }) - - It("should return an error", func() { - Expect(err).To(HaveOccurred()) - }) - }) - - PWhen("constructing a new queue client without dial blocking", func() { - // TODO: - }) - }) }) // TODO: new method testing is pending diff --git a/api/queues/queues_test.go b/api/queues/queues_test.go index 4f25d8b..1e2d32b 100644 --- a/api/queues/queues_test.go +++ b/api/queues/queues_test.go @@ -15,8 +15,6 @@ package queues import ( - "os" - "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -71,29 +69,4 @@ var _ = Describe("Queues API", func() { }) }) }) - - Describe("New method", func() { - When("constructing a new queue client without the membrane", func() { - BeforeEach(func() { - os.Setenv("NITRIC_SERVICE_DIAL_TIMEOUT", "10") - }) - AfterEach(func() { - os.Unsetenv("NITRIC_SERVICE_DIAL_TIMEOUT") - }) - - c, err := New() - - It("should return a nil client", func() { - Expect(c).To(BeNil()) - }) - - It("should return an error", func() { - Expect(err).To(HaveOccurred()) - }) - }) - - PWhen("constructing a new queue client without dial blocking", func() { - // TODO: - }) - }) }) diff --git a/api/secrets/secrets_test.go b/api/secrets/secrets_test.go index 4884baa..e4eff93 100644 --- a/api/secrets/secrets_test.go +++ b/api/secrets/secrets_test.go @@ -15,8 +15,6 @@ package secrets import ( - "os" - "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -71,29 +69,4 @@ var _ = Describe("Secrets API", func() { }) }) }) - - Describe("New method", func() { - When("Constructing a new Secrets client with no rpc server available", func() { - BeforeEach(func() { - os.Setenv("NITRIC_SERVICE_DIAL_TIMEOUT", "10") - }) - AfterEach(func() { - os.Unsetenv("NITRIC_SERVICE_DIAL_TIMEOUT") - }) - - c, err := New() - - It("should return a nil client", func() { - Expect(c).To(BeNil()) - }) - - It("should return an error", func() { - Expect(err).To(HaveOccurred()) - }) - }) - - PWhen("constructing a new Secrets client without dial blocking", func() { - // TODO: - }) - }) }) diff --git a/api/storage/storage_test.go b/api/storage/storage_test.go index 0be0c87..2ec9ac4 100644 --- a/api/storage/storage_test.go +++ b/api/storage/storage_test.go @@ -15,8 +15,6 @@ package storage import ( - "os" - "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -69,30 +67,4 @@ var _ = Describe("Storage API", func() { }) }) }) - - Describe("New()", func() { - Context("constructing a new storage client", func() { - When("the gRPC connection is unavailable", func() { - BeforeEach(func() { - os.Setenv("NITRIC_SERVICE_DIAL_TIMEOUT", "10") - }) - AfterEach(func() { - os.Unsetenv("NITRIC_SERVICE_DIAL_TIMEOUT") - }) - - s, err := New() - - It("should return an error", func() { - Expect(err).To(HaveOccurred()) - - By("not returning a storage client") - Expect(s).To(BeNil()) - }) - }) - - PWhen("constructing a new storage client without dial blocking", func() { - // TODO: Mock an available server to connect to - }) - }) - }) }) diff --git a/api/topics/topics_test.go b/api/topics/topics_test.go index 428c313..52fefbb 100644 --- a/api/topics/topics_test.go +++ b/api/topics/topics_test.go @@ -15,8 +15,6 @@ package topics import ( - "os" - "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -69,30 +67,4 @@ var _ = Describe("Topics API", func() { }) }) }) - - Describe("New()", func() { - Context("constructing a new topics client", func() { - When("the gRPC connection is unavailable", func() { - BeforeEach(func() { - os.Setenv("NITRIC_SERVICE_DIAL_TIMEOUT", "10") - }) - AfterEach(func() { - os.Unsetenv("NITRIC_SERVICE_DIAL_TIMEOUT") - }) - - ts, err := New() - - It("should return an error", func() { - Expect(err).To(HaveOccurred()) - - By("not returning a topics client") - Expect(ts).To(BeNil()) - }) - }) - - PWhen("constructing a new topics client without dial blocking", func() { - // TODO: Mock an available server to connect to - }) - }) - }) }) diff --git a/nitric/api.go b/nitric/api.go index 536d2bf..958665b 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -162,90 +162,90 @@ type Api interface { // // func() // func() error - // func(*apis.Context) - // func(*apis.Context) error - // func(*apis.Context) *apis.Context - // func(*apis.Context) (*apis.Context, error) - // func(*apis.Context, Handler[apis.Context]) *apis.Context - // func(*apis.Context, Handler[apis.Context]) error - // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) - // Middleware[apis.Context] - // Handler[apis.Context] + // func(*apis.Ctx) + // func(*apis.Ctx) error + // func(*apis.Ctx) *apis.Ctx + // func(*apis.Ctx) (*apis.Ctx, error) + // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx + // func(*apis.Ctx, Handler[apis.Ctx]) error + // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) + // Middleware[apis.Ctx] + // Handler[apis.Ctx] Get(path string, handler interface{}, opts ...MethodOption) // Put adds a Put method handler to the path with any specified opts. // Valid function signatures: // // func() // func() error - // func(*apis.Context) - // func(*apis.Context) error - // func(*apis.Context) *apis.Context - // func(*apis.Context) (*apis.Context, error) - // func(*apis.Context, Handler[apis.Context]) *apis.Context - // func(*apis.Context, Handler[apis.Context]) error - // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) - // Middleware[apis.Context] - // Handler[apis.Context] + // func(*apis.Ctx) + // func(*apis.Ctx) error + // func(*apis.Ctx) *apis.Ctx + // func(*apis.Ctx) (*apis.Ctx, error) + // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx + // func(*apis.Ctx, Handler[apis.Ctx]) error + // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) + // Middleware[apis.Ctx] + // Handler[apis.Ctx] Put(path string, handler interface{}, opts ...MethodOption) // Patch adds a Patch method handler to the path with any specified opts. // Valid function signatures: // // func() // func() error - // func(*apis.Context) - // func(*apis.Context) error - // func(*apis.Context) *apis.Context - // func(*apis.Context) (*apis.Context, error) - // func(*apis.Context, Handler[apis.Context]) *apis.Context - // func(*apis.Context, Handler[apis.Context]) error - // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) - // Middleware[apis.Context] - // Handler[apis.Context] + // func(*apis.Ctx) + // func(*apis.Ctx) error + // func(*apis.Ctx) *apis.Ctx + // func(*apis.Ctx) (*apis.Ctx, error) + // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx + // func(*apis.Ctx, Handler[apis.Ctx]) error + // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) + // Middleware[apis.Ctx] + // Handler[apis.Ctx] Patch(path string, handler interface{}, opts ...MethodOption) // Post adds a Post method handler to the path with any specified opts. // Valid function signatures: // // func() // func() error - // func(*apis.Context) - // func(*apis.Context) error - // func(*apis.Context) *apis.Context - // func(*apis.Context) (*apis.Context, error) - // func(*apis.Context, Handler[apis.Context]) *apis.Context - // func(*apis.Context, Handler[apis.Context]) error - // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) - // Middleware[apis.Context] - // Handler[apis.Context] + // func(*apis.Ctx) + // func(*apis.Ctx) error + // func(*apis.Ctx) *apis.Ctx + // func(*apis.Ctx) (*apis.Ctx, error) + // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx + // func(*apis.Ctx, Handler[apis.Ctx]) error + // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) + // Middleware[apis.Ctx] + // Handler[apis.Ctx] Post(path string, handler interface{}, opts ...MethodOption) // Delete adds a Delete method handler to the path with any specified opts. // Valid function signatures: // // func() // func() error - // func(*apis.Context) - // func(*apis.Context) error - // func(*apis.Context) *apis.Context - // func(*apis.Context) (*apis.Context, error) - // func(*apis.Context, Handler[apis.Context]) *apis.Context - // func(*apis.Context, Handler[apis.Context]) error - // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) - // Middleware[apis.Context] - // Handler[apis.Context] + // func(*apis.Ctx) + // func(*apis.Ctx) error + // func(*apis.Ctx) *apis.Ctx + // func(*apis.Ctx) (*apis.Ctx, error) + // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx + // func(*apis.Ctx, Handler[apis.Ctx]) error + // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) + // Middleware[apis.Ctx] + // Handler[apis.Ctx] Delete(path string, handler interface{}, opts ...MethodOption) // Options adds a Options method handler to the path with any specified opts. // Valid function signatures: // // func() // func() error - // func(*apis.Context) - // func(*apis.Context) error - // func(*apis.Context) *apis.Context - // func(*apis.Context) (*apis.Context, error) - // func(*apis.Context, Handler[apis.Context]) *apis.Context - // func(*apis.Context, Handler[apis.Context]) error - // func(*apis.Context, Handler[apis.Context]) (*apis.Context, error) - // Middleware[apis.Context] - // Handler[apis.Context] + // func(*apis.Ctx) + // func(*apis.Ctx) error + // func(*apis.Ctx) *apis.Ctx + // func(*apis.Ctx) (*apis.Ctx, error) + // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx + // func(*apis.Ctx, Handler[apis.Ctx]) error + // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) + // Middleware[apis.Ctx] + // Handler[apis.Ctx] Options(path string, handler interface{}, opts ...MethodOption) NewRoute(path string, middleware ...Middleware[httpx.Ctx]) Route } @@ -326,7 +326,7 @@ func (a *api) Get(match string, handler interface{}, opts ...MethodOption) { // Post adds a Post method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Post(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (a *api) Post(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) r.Post(handler, opts...) @@ -335,7 +335,7 @@ func (a *api) Post(match string, handler Middleware[httpx.Ctx], opts ...MethodOp // Patch adds a Patch method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Patch(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (a *api) Patch(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) r.Patch(handler, opts...) @@ -344,7 +344,7 @@ func (a *api) Patch(match string, handler Middleware[httpx.Ctx], opts ...MethodO // Put adds a Put method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Put(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (a *api) Put(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) r.Put(handler, opts...) @@ -353,7 +353,7 @@ func (a *api) Put(match string, handler Middleware[httpx.Ctx], opts ...MethodOpt // Delete adds a Delete method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Delete(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (a *api) Delete(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) r.Delete(handler, opts...) @@ -362,7 +362,7 @@ func (a *api) Delete(match string, handler Middleware[httpx.Ctx], opts ...Method // Options adds an Options method handler to the path with any specified opts. // Note: to chain middleware use handler.ComposeHttpMiddlware() -func (a *api) Options(match string, handler Middleware[httpx.Ctx], opts ...MethodOption) { +func (a *api) Options(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) r.Options(handler, opts...) diff --git a/nitric/bucket.go b/nitric/bucket.go index 980173a..0d6fc02 100644 --- a/nitric/bucket.go +++ b/nitric/bucket.go @@ -33,7 +33,22 @@ type bucket struct { type Bucket interface { Allow(BucketPermission, ...BucketPermission) (storage.Bucket, error) - On(storage.EventType, string, ...Middleware[storage.Ctx]) + + // On registers a handler for a specific event type on the bucket. + // Valid function signatures for middleware are: + // + // func() + // func() error + // func(*storage.Ctx) + // func(*storage.Ctx) error + // func(*storage.Ctx) *storage.Ctx + // func(*storage.Ctx) (*storage.Ctx, error) + // func(*storage.Ctx, Handler[storage.Ctx]) *storage.Ctx + // func(*storage.Ctx, Handler[storage.Ctx]) error + // func(*storage.Ctx, Handler[storage.Ctx]) (*storage.Ctx, error) + // Middleware[storage.Ctx] + // Handler[storage.Ctx] + On(storage.EventType, string, ...interface{}) } const ( @@ -102,7 +117,7 @@ func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermiss return m.storage.Bucket(b.name), nil } -func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter string, middleware ...Middleware[storage.Ctx]) { +func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter string, middleware ...interface{}) { var blobEventType storagepb.BlobEventType switch notificationType { case storage.WriteNotification: @@ -117,7 +132,12 @@ func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter KeyPrefixFilter: notificationPrefixFilter, } - composedHandler := Compose(middleware...) + middlewares, err := interfacesToMiddleware[storage.Ctx](middleware) + if err != nil { + panic(err) + } + + composedHandler := Compose(middlewares...) opts := &bucketEventWorkerOpts{ RegistrationRequest: registrationRequest, diff --git a/nitric/middleware.go b/nitric/middleware.go index 339d4db..ecb9ec0 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -30,6 +30,18 @@ func dummyHandler[T any](ctx *T) (*T, error) { return ctx, nil } +func interfacesToMiddleware[T any](mws []interface{}) ([]Middleware[T], error) { + mwares := make([]Middleware[T], len(mws)) + for i, mw := range mws { + mware, err := interfaceToMiddleware[T](mw) + if err != nil { + return nil, err + } + mwares[i] = mware + } + return mwares, nil +} + // interfaceToMiddleware - Converts a function to a Middleware // Valid function types are: // func() diff --git a/nitric/middleware_test.go b/nitric/middleware_test.go new file mode 100644 index 0000000..97346f5 --- /dev/null +++ b/nitric/middleware_test.go @@ -0,0 +1,129 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 nitric + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/golang/mock/gomock" +) + +var _ = Describe("middleware", func() { + ctrl := gomock.NewController(GinkgoT()) + + // func() + // func() error + // func(*T) + // func(*T) error + // func(*T) *T + // func(*T) (*T, error) + // func(*T, Handler[T]) *T + // func(*T, Handler[T]) error + // func(*T, Handler[T]) (*T, error) + // Middleware[T] + // Handler[T] + Context("interfaceToMiddleware", func() { + When("interface{} is func()", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[any](func() {}) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func() error", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[any](func() error { return nil }) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T)", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[string](func(*string) {}) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T) error", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[string](func(*string) error { return nil }) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T) *T", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[string](func(str *string) *string { return str }) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T) (*T, error)", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[string](func(str *string) (*string, error) { return str, nil }) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T, Handler[T]) *T", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[string](func(str *string, next Handler[string]) *string { return str }) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T, Handler[T]) error", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[string](func(str *string, next Handler[string]) error { return nil }) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T, Handler[T]) (*T, error)", func() { + It("should return a valid middleware", func() { + mw, err := interfaceToMiddleware[string](func(str *string, next Handler[string]) (*string, error) { return str, nil }) + + Expect(err).To(BeNil()) + Expect(mw).ToNot(BeNil()) + }) + }) + + When("interface{} is not a valid type", func() { + It("should return an error", func() { + mw, err := interfaceToMiddleware[string](func() (error, error) { return nil, nil }) + + Expect(err).ToNot(BeNil()) + Expect(mw).To(BeNil()) + }) + }) + }) +}) diff --git a/nitric/resources_suite_test.go b/nitric/resources_suite_test.go index e30441f..9d7d6b5 100644 --- a/nitric/resources_suite_test.go +++ b/nitric/resources_suite_test.go @@ -14,14 +14,14 @@ package nitric -// import ( -// "testing" +import ( + "testing" -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" -// ) + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) -// func TestResources(t *testing.T) { -// RegisterFailHandler(Fail) -// RunSpecs(t, "Resources Suite") -// } +func TestNitric(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Nitric Suite") +} diff --git a/nitric/schedule.go b/nitric/schedule.go index 80243a4..d6bad6c 100644 --- a/nitric/schedule.go +++ b/nitric/schedule.go @@ -22,17 +22,46 @@ import ( ) type Schedule interface { - Cron(cron string, middleware ...Middleware[schedules.Ctx]) - Every(rate string, middleware ...Middleware[schedules.Ctx]) + // Run middleware at a certain interval defined by the cronExpression. + // Valid function signatures for middleware are: + // + // func() + // func() error + // func(*schedules.Ctx) + // func(*schedules.Ctx) error + // func(*schedules.Ctx) *schedules.Ctx + // func(*schedules.Ctx) (*schedules.Ctx, error) + // func(*schedules.Ctx, Handler[schedules.Ctx]) *schedules.Ctx + // func(*schedules.Ctx, Handler[schedules.Ctx]) error + // func(*schedules.Ctx, Handler[schedules.Ctx]) (*schedules.Ctx, error) + // Middleware[schedules.Ctx] + // Handler[schedules.Ctx] + Cron(cron string, middleware ...interface{}) + + // Run middleware at a certain interval defined by the rate. The rate is e.g. '7 days'. All rates accept a number and a frequency. Valid frequencies are 'days', 'hours' or 'minutes'. + // Valid function signatures for middleware are: + // + // func() + // func() error + // func(*schedules.Ctx) + // func(*schedules.Ctx) error + // func(*schedules.Ctx) *schedules.Ctx + // func(*schedules.Ctx) (*schedules.Ctx, error) + // func(*schedules.Ctx, Handler[schedules.Ctx]) *schedules.Ctx + // func(*schedules.Ctx, Handler[schedules.Ctx]) error + // func(*schedules.Ctx, Handler[schedules.Ctx]) (*schedules.Ctx, error) + // Middleware[schedules.Ctx] + // Handler[schedules.Ctx] + Every(rate string, middleware ...interface{}) } type schedule struct { - Schedule - name string manager Manager } +var _ Schedule = (*schedule)(nil) + // NewSchedule provides a new schedule, which can be configured with a rate/cron and a callback to run on the schedule. func NewSchedule(name string) Schedule { return &schedule{ @@ -41,8 +70,7 @@ func NewSchedule(name string) Schedule { } } -// Run middleware at a certain interval defined by the cronExpression. -func (s *schedule) Cron(cron string, middleware ...Middleware[schedules.Ctx]) { +func (s *schedule) Cron(cron string, middleware ...interface{}) { scheduleCron := &schedulespb.ScheduleCron{ Expression: cron, } @@ -54,7 +82,12 @@ func (s *schedule) Cron(cron string, middleware ...Middleware[schedules.Ctx]) { }, } - composeHandler := Compose(middleware...) + middlewares, err := interfacesToMiddleware[schedules.Ctx](middleware) + if err != nil { + panic(err) + } + + composeHandler := Compose(middlewares...) opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, @@ -68,8 +101,7 @@ func (s *schedule) Cron(cron string, middleware ...Middleware[schedules.Ctx]) { }, "-"), worker) } -// Run middleware at a certain interval defined by the rate. The rate is e.g. '7 days'. All rates accept a number and a frequency. Valid frequencies are 'days', 'hours' or 'minutes'. -func (s *schedule) Every(rate string, middleware ...Middleware[schedules.Ctx]) { +func (s *schedule) Every(rate string, middleware ...interface{}) { scheduleEvery := &schedulespb.ScheduleEvery{ Rate: rate, } @@ -81,7 +113,12 @@ func (s *schedule) Every(rate string, middleware ...Middleware[schedules.Ctx]) { }, } - composeHandler := Compose(middleware...) + middlewares, err := interfacesToMiddleware[schedules.Ctx](middleware) + if err != nil { + panic(err) + } + + composeHandler := Compose(middlewares...) opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, diff --git a/nitric/topic.go b/nitric/topic.go index fefb0bd..5dfad31 100644 --- a/nitric/topic.go +++ b/nitric/topic.go @@ -39,7 +39,20 @@ type SubscribableTopic interface { Allow(TopicPermission, ...TopicPermission) (Topic, error) // Subscribe will register and start a subscription handler that will be called for all events from this topic. - Subscribe(...Middleware[topics.Ctx]) + // Valid function signatures for middleware are: + // + // func() + // func() error + // func(*topics.Ctx) + // func(*topics.Ctx) error + // func(*topics.Ctx) *topics.Ctx + // func(*topics.Ctx) (*topics.Ctx, error) + // func(*topics.Ctx, Handler[topics.Ctx]) *topics.Ctx + // func(*topics.Ctx, Handler[topics.Ctx]) error + // func(*topics.Ctx, Handler[topics.Ctx]) (*topics.Ctx, error) + // Middleware[topics.Ctx] + // Handler[topics.Ctx] + Subscribe(...interface{}) } type topic struct { @@ -111,11 +124,17 @@ func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...Top }, nil } -func (t *subscribableTopic) Subscribe(middleware ...Middleware[topics.Ctx]) { +func (t *subscribableTopic) Subscribe(middleware ...interface{}) { registrationRequest := &topicspb.RegistrationRequest{ TopicName: t.name, } - composeHandler := Compose(middleware...) + + middlewares, err := interfacesToMiddleware[topics.Ctx](middleware) + if err != nil { + panic(err) + } + + composeHandler := Compose(middlewares...) opts := &subscriptionWorkerOpts{ RegistrationRequest: registrationRequest, diff --git a/nitric/websocket.go b/nitric/websocket.go index 261de30..57f3db7 100644 --- a/nitric/websocket.go +++ b/nitric/websocket.go @@ -70,6 +70,20 @@ func (w *websocket) Name() string { return w.name } +// On registers a handler for a specific event type on the websocket +// Valid function signatures for middleware are: +// +// func() +// func() error +// func(*websockets.Ctx) +// func(*websockets.Ctx) error +// func(*websockets.Ctx) *websockets.Ctx +// func(*websockets.Ctx) (*websockets.Ctx, error) +// func(*websockets.Ctx, Handler[websockets.Ctx]) *websockets.Ctx +// func(*websockets.Ctx, Handler[websockets.Ctx]) error +// func(*websockets.Ctx, Handler[websockets.Ctx]) (*websockets.Ctx, error) +// Middleware[websockets.Ctx] +// Handler[websockets.Ctx] func (w *websocket) On(eventType websockets.EventType, middleware ...Middleware[websockets.Ctx]) { var _eventType websocketsv1.WebsocketEventType switch eventType { From 61f9ebf80b571c17b95664a8dede1973c782291f Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 17:54:02 +1000 Subject: [PATCH 11/42] update tests. --- Makefile | 4 ++-- nitric/middleware_test.go | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 338b2a5..f061e1a 100644 --- a/Makefile +++ b/Makefile @@ -58,9 +58,9 @@ generate: # Runs tests for coverage upload to codecov.io test-ci: generate @echo Testing Nitric Go SDK - @go run github.com/onsi/ginkgo/ginkgo -cover -outputdir=./ -coverprofile=all.coverprofile ./resources/... ./api/... ./faas/... + @go run github.com/onsi/ginkgo/ginkgo -cover -outputdir=./ -coverprofile=all.coverprofile ./nitric/... ./api/... .PHONY: test test: generate @echo Testing Nitric Go SDK - @go run github.com/onsi/ginkgo/ginkgo -cover ./resources/... ./api/... ./faas/... \ No newline at end of file + @go run github.com/onsi/ginkgo/ginkgo -cover ./nitric/... ./api/... \ No newline at end of file diff --git a/nitric/middleware_test.go b/nitric/middleware_test.go index 97346f5..081dc1d 100644 --- a/nitric/middleware_test.go +++ b/nitric/middleware_test.go @@ -17,13 +17,9 @@ package nitric import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/golang/mock/gomock" ) var _ = Describe("middleware", func() { - ctrl := gomock.NewController(GinkgoT()) - // func() // func() error // func(*T) From 8f164c231cb0221c659d9000620b4a4d2455ec76 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 18 Sep 2024 18:04:42 +1000 Subject: [PATCH 12/42] remove debug messages. --- .golangci.yml | 3 --- nitric/api_workers.go | 4 +--- nitric/bucket_workers.go | 4 +--- nitric/schedule_workers.go | 4 +--- nitric/topic_workers.go | 4 +--- nitric/websocket_workers.go | 4 +--- 6 files changed, 5 insertions(+), 18 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 336c9a5..14f9120 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,8 +1,5 @@ run: timeout: "5m" - skip-files: - - tools/tools.go - - doc.go linters: disable-all: true diff --git a/nitric/api_workers.go b/nitric/api_workers.go index be99df4..397379c 100644 --- a/nitric/api_workers.go +++ b/nitric/api_workers.go @@ -17,7 +17,6 @@ package nitric import ( "context" errorsstd "errors" - "fmt" "io" "google.golang.org/grpc" @@ -73,8 +72,7 @@ func (a *apiWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Function connected with Nitric server - fmt.Println("Function connected with Nitric server") + // Do nothing } else if err == nil && resp.GetHttpRequest() != nil { ctx = httpx.NewCtx(resp) diff --git a/nitric/bucket_workers.go b/nitric/bucket_workers.go index 703b4af..0220add 100644 --- a/nitric/bucket_workers.go +++ b/nitric/bucket_workers.go @@ -17,7 +17,6 @@ package nitric import ( "context" errorsstd "errors" - "fmt" "io" "google.golang.org/grpc" @@ -70,8 +69,7 @@ func (b *bucketEventWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Blob Notification has connected with Nitric server - fmt.Println("BlobEventWorker connected with Nitric server") + // Do nothing } else if err == nil && resp.GetBlobEventRequest() != nil { ctx = storage.NewCtx(resp) ctx, err = b.middleware(ctx, dummyHandler) diff --git a/nitric/schedule_workers.go b/nitric/schedule_workers.go index 541d1af..9ff12d5 100644 --- a/nitric/schedule_workers.go +++ b/nitric/schedule_workers.go @@ -17,7 +17,6 @@ package nitric import ( "context" errorsstd "errors" - "fmt" "io" "google.golang.org/grpc" @@ -70,8 +69,7 @@ func (i *scheduleWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Interval worker has connected with Nitric server - fmt.Println("IntervalWorker connected with Nitric server") + // Do nothing } else if err == nil && resp.GetIntervalRequest() != nil { ctx = schedules.NewCtx(resp) ctx, err = i.middleware(ctx, dummyHandler) diff --git a/nitric/topic_workers.go b/nitric/topic_workers.go index d929c5d..cb37d86 100644 --- a/nitric/topic_workers.go +++ b/nitric/topic_workers.go @@ -16,7 +16,6 @@ package nitric import ( "context" - "fmt" "io" "google.golang.org/grpc" @@ -71,8 +70,7 @@ func (s *subscriptionWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Subscription worker has connected with Nitric server - fmt.Println("SubscriptionWorker connected with Nitric server") + // Do nothing } else if err == nil && resp.GetMessageRequest() != nil { ctx = topics.NewCtx(resp) ctx, err = s.middleware(ctx, dummyHandler) diff --git a/nitric/websocket_workers.go b/nitric/websocket_workers.go index cff03dd..ed11dcf 100644 --- a/nitric/websocket_workers.go +++ b/nitric/websocket_workers.go @@ -17,7 +17,6 @@ package nitric import ( "context" errorsstd "errors" - "fmt" "io" "google.golang.org/grpc" @@ -70,8 +69,7 @@ func (w *websocketWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Blob Notification has connected with Nitric server - fmt.Println("WebsocketWorker connected with Nitric server") + // Do nothing } else if err == nil && resp.GetWebsocketEventRequest() != nil { ctx = websockets.NewCtx(resp) ctx, err = w.middleware(ctx, dummyHandler) From 3c5a4840f6964152908e905548cb3227cf63d6e9 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Thu, 19 Sep 2024 10:49:39 +1000 Subject: [PATCH 13/42] wip --- Makefile | 9 +- api/keyvalue/keyvalue.go | 59 --- api/keyvalue/keyvalue_test.go | 71 --- api/queues/queues.go | 58 -- api/queues/queues_test.go | 72 --- api/secrets/secret_ref.go | 69 --- api/secrets/secret_value.go | 42 -- api/secrets/secret_value_test.go | 79 --- api/secrets/secret_version_ref.go | 67 --- api/secrets/secret_version_ref_test.go | 149 ------ api/secrets/secrets.go | 59 --- api/secrets/secrets_test.go | 72 --- api/storage/bucket.go | 69 --- api/storage/file.go | 140 ----- api/storage/file_test.go | 499 ------------------ api/storage/storage.go | 59 --- api/storage/storage_test.go | 70 --- api/topics/topics.go | 57 -- api/topics/topics_test.go | 70 --- licenses.go | 14 +- mocks/mockapi/keyvalue.go | 151 ------ mocks/mockapi/queues.go | 117 ---- mocks/mockapi/secrets.go | 130 ----- mocks/mockapi/storage.go | 116 ---- mocks/mockapi/topics.go | 107 ---- nitric/api.go | 15 +- nitric/api_test.go | 148 ------ nitric/api_workers.go | 6 +- {api => nitric}/apis/context.go | 2 +- {api => nitric}/apis/request.go | 14 +- {api => nitric}/apis/response.go | 0 nitric/bucket.go | 23 +- nitric/bucket_test.go | 87 --- nitric/bucket_workers.go | 6 +- {api => nitric}/errors/api_error.go | 2 +- {api => nitric}/errors/codes/codes.go | 0 nitric/keyvalue.go | 22 +- .../keyvalue/keyvalue_suite_test.go | 0 {api => nitric}/keyvalue/store.go | 38 +- {api => nitric}/keyvalue/store_test.go | 8 +- nitric/manager.go | 45 +- nitric/manager_test.go | 2 +- nitric/oidc.go | 2 +- nitric/options.go | 3 +- nitric/queue.go | 22 +- nitric/queue_test.go | 89 ---- .../task.go => nitric/queues/message.go | 12 +- .../queues/message_test.go | 2 +- {api => nitric}/queues/queue.go | 38 +- {api => nitric}/queues/queue_test.go | 13 +- {api => nitric}/queues/queues_suite_test.go | 0 nitric/schedule.go | 6 +- nitric/schedule_test.go | 114 ---- nitric/schedule_workers.go | 6 +- {api => nitric}/schedules/context.go | 2 +- {api => nitric}/schedules/request.go | 4 +- {api => nitric}/schedules/response.go | 0 nitric/secret.go | 21 +- nitric/secret_test.go | 87 --- nitric/secrets/secrets.go | 112 ++++ {api => nitric}/secrets/secrets_suite_test.go | 0 .../secrets/secrets_test.go | 92 +--- nitric/storage/bucket.go | 191 +++++++ {api => nitric}/storage/bucket_test.go | 57 +- {api => nitric}/storage/context.go | 0 {api => nitric}/storage/request.go | 0 {api => nitric}/storage/response.go | 0 {api => nitric}/storage/storage_suite_test.go | 0 nitric/topic.go | 34 +- nitric/topic_test.go | 85 --- nitric/topic_workers.go | 6 +- {api => nitric}/topics/context.go | 0 {api => nitric}/topics/request.go | 0 {api => nitric}/topics/response.go | 0 {api => nitric}/topics/topic.go | 37 +- {api => nitric}/topics/topic_test.go | 4 +- {api => nitric}/topics/topics_suite_test.go | 0 nitric/websocket.go | 42 +- nitric/websocket_workers.go | 6 +- {api => nitric}/websockets/context.go | 0 {api => nitric}/websockets/request.go | 0 {api => nitric}/websockets/response.go | 0 82 files changed, 570 insertions(+), 3340 deletions(-) delete mode 100644 api/keyvalue/keyvalue.go delete mode 100644 api/keyvalue/keyvalue_test.go delete mode 100644 api/queues/queues.go delete mode 100644 api/queues/queues_test.go delete mode 100644 api/secrets/secret_ref.go delete mode 100644 api/secrets/secret_value.go delete mode 100644 api/secrets/secret_value_test.go delete mode 100644 api/secrets/secret_version_ref.go delete mode 100644 api/secrets/secret_version_ref_test.go delete mode 100644 api/secrets/secrets.go delete mode 100644 api/secrets/secrets_test.go delete mode 100644 api/storage/bucket.go delete mode 100644 api/storage/file.go delete mode 100644 api/storage/file_test.go delete mode 100644 api/storage/storage.go delete mode 100644 api/storage/storage_test.go delete mode 100644 api/topics/topics.go delete mode 100644 api/topics/topics_test.go delete mode 100644 mocks/mockapi/keyvalue.go delete mode 100644 mocks/mockapi/queues.go delete mode 100644 mocks/mockapi/secrets.go delete mode 100644 mocks/mockapi/storage.go delete mode 100644 mocks/mockapi/topics.go delete mode 100644 nitric/api_test.go rename {api => nitric}/apis/context.go (98%) rename {api => nitric}/apis/request.go (77%) rename {api => nitric}/apis/response.go (100%) delete mode 100644 nitric/bucket_test.go rename {api => nitric}/errors/api_error.go (97%) rename {api => nitric}/errors/codes/codes.go (100%) rename {api => nitric}/keyvalue/keyvalue_suite_test.go (100%) rename {api => nitric}/keyvalue/store.go (75%) rename {api => nitric}/keyvalue/store_test.go (97%) delete mode 100644 nitric/queue_test.go rename api/queues/task.go => nitric/queues/message.go (87%) rename api/queues/task_test.go => nitric/queues/message_test.go (98%) rename {api => nitric}/queues/queue.go (72%) rename {api => nitric}/queues/queue_test.go (96%) rename {api => nitric}/queues/queues_suite_test.go (100%) delete mode 100644 nitric/schedule_test.go rename {api => nitric}/schedules/context.go (97%) rename {api => nitric}/schedules/request.go (90%) rename {api => nitric}/schedules/response.go (100%) delete mode 100644 nitric/secret_test.go create mode 100644 nitric/secrets/secrets.go rename {api => nitric}/secrets/secrets_suite_test.go (100%) rename api/secrets/secret_ref_test.go => nitric/secrets/secrets_test.go (55%) create mode 100644 nitric/storage/bucket.go rename {api => nitric}/storage/bucket_test.go (70%) rename {api => nitric}/storage/context.go (100%) rename {api => nitric}/storage/request.go (100%) rename {api => nitric}/storage/response.go (100%) rename {api => nitric}/storage/storage_suite_test.go (100%) delete mode 100644 nitric/topic_test.go rename {api => nitric}/topics/context.go (100%) rename {api => nitric}/topics/request.go (100%) rename {api => nitric}/topics/response.go (100%) rename {api => nitric}/topics/topic.go (67%) rename {api => nitric}/topics/topic_test.go (98%) rename {api => nitric}/topics/topics_suite_test.go (100%) rename {api => nitric}/websockets/context.go (100%) rename {api => nitric}/websockets/request.go (100%) rename {api => nitric}/websockets/response.go (100%) diff --git a/Makefile b/Makefile index f061e1a..18b9f6f 100644 --- a/Makefile +++ b/Makefile @@ -49,18 +49,13 @@ generate: go run github.com/golang/mock/mockgen github.com/nitrictech/nitric/core/pkg/proto/secrets/v1 SecretManagerClient > mocks/secrets.go go run github.com/golang/mock/mockgen github.com/nitrictech/nitric/core/pkg/proto/topics/v1 TopicsClient > mocks/topics.go go run github.com/golang/mock/mockgen -package mock_v1 google.golang.org/grpc ClientConnInterface > mocks/grpc_clientconn.go - go run github.com/golang/mock/mockgen -package mockapi github.com/nitrictech/go-sdk/api/keyvalue KeyValue,Store > mocks/mockapi/keyvalue.go - go run github.com/golang/mock/mockgen -package mockapi github.com/nitrictech/go-sdk/api/queues Queues,Queue > mocks/mockapi/queues.go - go run github.com/golang/mock/mockgen -package mockapi github.com/nitrictech/go-sdk/api/secrets Secrets,SecretRef > mocks/mockapi/secrets.go - go run github.com/golang/mock/mockgen -package mockapi github.com/nitrictech/go-sdk/api/storage Storage,Bucket > mocks/mockapi/storage.go - go run github.com/golang/mock/mockgen -package mockapi github.com/nitrictech/go-sdk/api/topics Topics,Topic > mocks/mockapi/topics.go # Runs tests for coverage upload to codecov.io test-ci: generate @echo Testing Nitric Go SDK - @go run github.com/onsi/ginkgo/ginkgo -cover -outputdir=./ -coverprofile=all.coverprofile ./nitric/... ./api/... + @go run github.com/onsi/ginkgo/ginkgo -cover -outputdir=./ -coverprofile=all.coverprofile ./... .PHONY: test test: generate @echo Testing Nitric Go SDK - @go run github.com/onsi/ginkgo/ginkgo -cover ./nitric/... ./api/... \ No newline at end of file + @go run github.com/onsi/ginkgo/ginkgo -cover ./... \ No newline at end of file diff --git a/api/keyvalue/keyvalue.go b/api/keyvalue/keyvalue.go deleted file mode 100644 index 0875f5d..0000000 --- a/api/keyvalue/keyvalue.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 keyvalue - -import ( - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/constants" - v1 "github.com/nitrictech/nitric/core/pkg/proto/kvstore/v1" -) - -// KeyValue - Idiomatic interface for the nitric Key Value Store Service -type KeyValue interface { - // Gets a store instance that refers to the store at the specified path. - Store(string) Store -} - -type keyValueImpl struct { - kvClient v1.KvStoreClient -} - -func (k *keyValueImpl) Store(name string) Store { - return &storeImpl{ - name: name, - kvClient: k.kvClient, - } -} - -// New - Construct a new Key Value Store Client with default options -func New() (KeyValue, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "KeyValue.New: Unable to reach KVStoreServiceServer", - err, - ) - } - - kvClient := v1.NewKvStoreClient(conn) - - return &keyValueImpl{ - kvClient: kvClient, - }, nil -} diff --git a/api/keyvalue/keyvalue_test.go b/api/keyvalue/keyvalue_test.go deleted file mode 100644 index 4134b3c..0000000 --- a/api/keyvalue/keyvalue_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 keyvalue - -import ( - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - mock_v1 "github.com/nitrictech/go-sdk/mocks" -) - -var _ = Describe("KeyValue API", func() { - var ( - ctrl *gomock.Controller - mockKV *mock_v1.MockKvStoreClient - kv *keyValueImpl - store Store - storeI *storeImpl - ok bool - storeName string - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockKV = mock_v1.NewMockKvStoreClient(ctrl) - kv = &keyValueImpl{kvClient: mockKV} - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Store()", func() { - Context("Given a valid KvStoreClient", func() { - BeforeEach(func() { - storeName = "test-store" - store = kv.Store(storeName) - storeI, ok = store.(*storeImpl) - }) - - When("creating new Store instance", func() { - It("should return an instance of storeImpl", func() { - Expect(ok).To(BeTrue()) - }) - - It("should have the provided store name", func() { - Expect(storeI.name).To(Equal(storeName)) - }) - - It("should share the KeyValue store's gRPC client", func() { - Expect(storeI.kvClient).To(Equal(mockKV)) - }) - }) - }) - }) -}) - -// TODO: new method testing is pending diff --git a/api/queues/queues.go b/api/queues/queues.go deleted file mode 100644 index f490d5d..0000000 --- a/api/queues/queues.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 queues - -import ( - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/constants" - v1 "github.com/nitrictech/nitric/core/pkg/proto/queues/v1" -) - -// Queues - Idiomatic interface for the nitric queue service -type Queues interface { - Queue(string) Queue -} - -type queuesImpl struct { - queueClient v1.QueuesClient -} - -func (q *queuesImpl) Queue(name string) Queue { - return &queueImpl{ - name: name, - queueClient: q.queueClient, - } -} - -// New - Construct a new Queueing Client with default options -func New() (Queues, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "Queues.New: Unable to reach QueueServiceServer", - err, - ) - } - - qClient := v1.NewQueuesClient(conn) - - return &queuesImpl{ - queueClient: qClient, - }, nil -} diff --git a/api/queues/queues_test.go b/api/queues/queues_test.go deleted file mode 100644 index 1e2d32b..0000000 --- a/api/queues/queues_test.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 queues - -import ( - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - mock_v1 "github.com/nitrictech/go-sdk/mocks" -) - -var _ = Describe("Queues API", func() { - var ( - ctrl *gomock.Controller - mockQ *mock_v1.MockQueuesClient - queues *queuesImpl - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockQ = mock_v1.NewMockQueuesClient(ctrl) - queues = &queuesImpl{ - queueClient: mockQ, - } - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Queue method", func() { - When("creating a new Queue reference", func() { - var ( - q Queue - queueName string - qImpl *queueImpl - ok bool - ) - - BeforeEach(func() { - queueName = "test-queue" - q = queues.Queue(queueName) - qImpl, ok = q.(*queueImpl) - }) - - It("should be an instance of queueImpl", func() { - Expect(ok).To(BeTrue()) - }) - - It("should have the provided queue name", func() { - Expect(q.Name()).To(Equal(queueName)) - }) - - It("should share the Queue's gRPC client", func() { - Expect(qImpl.queueClient).To(Equal(mockQ)) - }) - }) - }) -}) diff --git a/api/secrets/secret_ref.go b/api/secrets/secret_ref.go deleted file mode 100644 index dc7d1aa..0000000 --- a/api/secrets/secret_ref.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 secrets - -import ( - "context" - - "github.com/nitrictech/go-sdk/api/errors" - v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" -) - -// SecretRef is a reference to a cloud secret for secret storage. -type SecretRef interface { - Name() string - Put(context.Context, []byte) (SecretVersionRef, error) - Version(string) SecretVersionRef - Latest() SecretVersionRef -} - -type secretRefImpl struct { - name string - secretClient v1.SecretManagerClient -} - -func (s *secretRefImpl) Name() string { - return s.name -} - -func (s *secretRefImpl) Put(ctx context.Context, sec []byte) (SecretVersionRef, error) { - resp, err := s.secretClient.Put(ctx, &v1.SecretPutRequest{ - Secret: &v1.Secret{ - Name: s.name, - }, - Value: sec, - }) - if err != nil { - return nil, errors.FromGrpcError(err) - } - - return &secretVersionRefImpl{ - secretClient: s.secretClient, - version: resp.GetSecretVersion().Version, - secret: s, - }, nil -} - -func (s *secretRefImpl) Version(name string) SecretVersionRef { - return &secretVersionRefImpl{ - secret: s, - secretClient: s.secretClient, - version: name, - } -} - -func (s *secretRefImpl) Latest() SecretVersionRef { - return s.Version("latest") -} diff --git a/api/secrets/secret_value.go b/api/secrets/secret_value.go deleted file mode 100644 index e941f61..0000000 --- a/api/secrets/secret_value.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 secrets - -// SecretValue - Interface -type SecretValue interface { - // Version - Returns a reference to the version of this value - Version() SecretVersionRef - // AsBytes - Returns the secret value as bytes - AsBytes() []byte - // AsString - Returns the secret value as a string - AsString() string -} - -type secretValueImpl struct { - version SecretVersionRef - val []byte -} - -func (s *secretValueImpl) Version() SecretVersionRef { - return s.version -} - -func (s *secretValueImpl) AsBytes() []byte { - return s.val -} - -func (s *secretValueImpl) AsString() string { - return string(s.AsBytes()) -} diff --git a/api/secrets/secret_value_test.go b/api/secrets/secret_value_test.go deleted file mode 100644 index 15ed22d..0000000 --- a/api/secrets/secret_value_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 secrets - -import ( - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - mock_v1 "github.com/nitrictech/go-sdk/mocks" -) - -var _ = Describe("secretValueImpl", func() { - var ( - ctrl *gomock.Controller - mockSC *mock_v1.MockSecretManagerClient - secretName string - versionName string - sv SecretVersionRef - secretValue SecretValue - value []byte - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockSC = mock_v1.NewMockSecretManagerClient(ctrl) - secretName = "test-secret" - versionName = "test-version" - - sv = &secretVersionRefImpl{ - secretClient: mockSC, - secret: &secretRefImpl{ - name: secretName, - secretClient: mockSC, - }, - version: versionName, - } - - value = []byte("ssssshhhh... it's a secret") - secretValue = &secretValueImpl{ - version: sv, - val: value, - } - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Version", func() { - It("should return the correct secret version reference", func() { - Expect(secretValue.Version()).To(Equal(sv)) - }) - }) - - Describe("AsBytes", func() { - It("should return the correct secret value as bytes", func() { - Expect(secretValue.AsBytes()).To(Equal(value)) - }) - }) - - Describe("AsString", func() { - It("should return the correct secret value as string", func() { - Expect(secretValue.AsString()).To(Equal(string(value))) - }) - }) -}) diff --git a/api/secrets/secret_version_ref.go b/api/secrets/secret_version_ref.go deleted file mode 100644 index bf68513..0000000 --- a/api/secrets/secret_version_ref.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 secrets - -import ( - "context" - - "github.com/nitrictech/go-sdk/api/errors" - v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" -) - -// SecretVersionRef - A reference to a secret version -type SecretVersionRef interface { - // Access - Retrieve the value of the secret - Access(ctx context.Context) (SecretValue, error) - Secret() SecretRef - Version() string -} - -type secretVersionRefImpl struct { - secretClient v1.SecretManagerClient - secret SecretRef - version string -} - -func (s *secretVersionRefImpl) Secret() SecretRef { - return s.secret -} - -func (s *secretVersionRefImpl) Version() string { - return s.version -} - -func (s *secretVersionRefImpl) Access(ctx context.Context) (SecretValue, error) { - r, err := s.secretClient.Access(ctx, &v1.SecretAccessRequest{ - SecretVersion: &v1.SecretVersion{ - Secret: &v1.Secret{ - Name: s.secret.Name(), - }, - Version: s.version, - }, - }) - if err != nil { - return nil, errors.FromGrpcError(err) - } - - return &secretValueImpl{ - version: &secretVersionRefImpl{ - secretClient: s.secretClient, - secret: s.secret, - version: r.GetSecretVersion().GetVersion(), - }, - val: r.GetValue(), - }, nil -} diff --git a/api/secrets/secret_version_ref_test.go b/api/secrets/secret_version_ref_test.go deleted file mode 100644 index 637926b..0000000 --- a/api/secrets/secret_version_ref_test.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 secrets - -import ( - "context" - "errors" - "strings" - - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - mock_v1 "github.com/nitrictech/go-sdk/mocks" - v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" -) - -var _ = Describe("secretVersionRefImpl", func() { - var ( - ctrl *gomock.Controller - mockSC *mock_v1.MockSecretManagerClient - secretName string - versionName string - sv SecretVersionRef - sr SecretRef - ctx context.Context - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockSC = mock_v1.NewMockSecretManagerClient(ctrl) - secretName = "test-secret" - versionName = "test-version" - - sr = &secretRefImpl{ - name: secretName, - secretClient: mockSC, - } - - sv = &secretVersionRefImpl{ - secretClient: mockSC, - secret: sr, - version: versionName, - } - ctx = context.Background() - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Access", func() { - var secretValue []byte - - BeforeEach(func() { - secretValue = []byte("super-secret-value") - }) - - When("the RPC operation is successful", func() { - BeforeEach(func() { - mockSC.EXPECT().Access(gomock.Any(), &v1.SecretAccessRequest{ - SecretVersion: &v1.SecretVersion{ - Secret: &v1.Secret{ - Name: secretName, - }, - Version: versionName, - }, - }).Return( - &v1.SecretAccessResponse{ - SecretVersion: &v1.SecretVersion{ - Secret: &v1.Secret{ - Name: secretName, - }, - Version: versionName, - }, - Value: secretValue, - }, nil, - ) - }) - - It("should return the secret value", func() { - svValue, err := sv.Access(ctx) - - By("not returning an error") - Expect(err).ToNot(HaveOccurred()) - - By("returning a SecretValue") - Expect(svValue).ToNot(BeNil()) - - By("returning the correct secret value") - Expect(svValue.AsBytes()).To(Equal(secretValue)) - - By("returning the correct secret version") - Expect(svValue.Version().Version()).To(Equal(versionName)) - }) - }) - - When("the RPC operation fails", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "Internal Error" - mockSC.EXPECT().Access(gomock.Any(), gomock.Any()).Return( - nil, - errors.New(errorMsg), - ).Times(1) - }) - - It("should return an error", func() { - svValue, err := sv.Access(ctx) - - By("returning the error") - Expect(err).To(HaveOccurred()) - Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - - By("returning a nil SecretValue") - Expect(svValue).To(BeNil()) - }) - }) - }) - - Context("Version", func() { - When("retrieving the version of a secretVersionRefImpl", func() { - It("should return it's internal version field", func() { - Expect(sv.Version()).To(Equal(versionName)) - }) - }) - }) - - Context("Secret", func() { - When("retrieving the parent secret of a secretVersionRefImpl", func() { - It("should return it's internal secret field", func() { - Expect(sv.Secret()).To(Equal(sr)) - }) - }) - }) -}) diff --git a/api/secrets/secrets.go b/api/secrets/secrets.go deleted file mode 100644 index 0df759a..0000000 --- a/api/secrets/secrets.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 secrets - -import ( - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/constants" - v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" -) - -// Secrets - Base client for the Nitric Secrets service -type Secrets interface { - // Secret - Creates a new secret reference - Secret(string) SecretRef -} - -type secretsImpl struct { - secretClient v1.SecretManagerClient -} - -func (s *secretsImpl) Secret(name string) SecretRef { - return &secretRefImpl{ - name: name, - secretClient: s.secretClient, - } -} - -// New - Create a new Secrets client -func New() (Secrets, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "Secrets.New: Unable to reach SecretsServiceServer", - err, - ) - } - - sClient := v1.NewSecretManagerClient(conn) - - return &secretsImpl{ - secretClient: sClient, - }, nil -} diff --git a/api/secrets/secrets_test.go b/api/secrets/secrets_test.go deleted file mode 100644 index e4eff93..0000000 --- a/api/secrets/secrets_test.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 secrets - -import ( - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - mock_v1 "github.com/nitrictech/go-sdk/mocks" -) - -var _ = Describe("Secrets API", func() { - var ( - ctrl *gomock.Controller - mockSC *mock_v1.MockSecretManagerClient - secrets *secretsImpl - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockSC = mock_v1.NewMockSecretManagerClient(ctrl) - secrets = &secretsImpl{ - secretClient: mockSC, - } - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Secret method", func() { - When("creating a new Secret reference", func() { - var ( - sr SecretRef - secretsName string - srImpl *secretRefImpl - ok bool - ) - - BeforeEach(func() { - secretsName = "test-secret" - sr = secrets.Secret(secretsName) - srImpl, ok = sr.(*secretRefImpl) - }) - - It("should be an instance of secretsImpl", func() { - Expect(ok).To(BeTrue()) - }) - - It("should have the provided secrets name", func() { - Expect(sr.Name()).To(Equal(secretsName)) - }) - - It("should share the Secret's gRPC client", func() { - Expect(srImpl.secretClient).To(Equal(mockSC)) - }) - }) - }) -}) diff --git a/api/storage/bucket.go b/api/storage/bucket.go deleted file mode 100644 index 537be8d..0000000 --- a/api/storage/bucket.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 storage - -import ( - "context" - - v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" -) - -// Cloud storage bucket resource for large file storage. -type Bucket interface { - // File - Get a file reference for in this bucket - File(key string) File - // Files - Get all file references for this bucket - Files(ctx context.Context) ([]File, error) - // Name - Get the name of the bucket - Name() string -} - -type bucketImpl struct { - storageClient v1.StorageClient - name string -} - -func (b *bucketImpl) File(key string) File { - return &fileImpl{ - storageClient: b.storageClient, - bucket: b.name, - key: key, - } -} - -func (b *bucketImpl) Files(ctx context.Context) ([]File, error) { - resp, err := b.storageClient.ListBlobs(ctx, &v1.StorageListBlobsRequest{ - BucketName: b.name, - }) - if err != nil { - return nil, err - } - - fileRefs := make([]File, 0) - - for _, f := range resp.Blobs { - fileRefs = append(fileRefs, &fileImpl{ - storageClient: b.storageClient, - bucket: b.name, - key: f.Key, - }) - } - - return fileRefs, nil -} - -func (b *bucketImpl) Name() string { - return b.name -} diff --git a/api/storage/file.go b/api/storage/file.go deleted file mode 100644 index 180c138..0000000 --- a/api/storage/file.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 storage - -import ( - "context" - "fmt" - "time" - - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" -) - -type Mode int - -const ( - ModeRead Mode = iota - ModeWrite -) - -// File - A file reference for a bucket -type File interface { - // Name - Get the name of the file - Name() string - // Read - Read this object - Read(ctx context.Context) ([]byte, error) - // Write - Write this object - Write(ctx context.Context, data []byte) error - // Delete - Delete this object - Delete(ctx context.Context) error - // UploadUrl - Creates a signed Url for uploading this file reference - UploadUrl(ctx context.Context, expiry time.Duration) (string, error) - // DownloadUrl - Creates a signed Url for downloading this file reference - DownloadUrl(ctx context.Context, expiry time.Duration) (string, error) -} - -type fileImpl struct { - bucket string - key string - storageClient v1.StorageClient -} - -func (o *fileImpl) Name() string { - return o.key -} - -func (o *fileImpl) Read(ctx context.Context) ([]byte, error) { - r, err := o.storageClient.Read(ctx, &v1.StorageReadRequest{ - BucketName: o.bucket, - Key: o.key, - }) - if err != nil { - return nil, errors.FromGrpcError(err) - } - - return r.GetBody(), nil -} - -func (o *fileImpl) Write(ctx context.Context, content []byte) error { - if _, err := o.storageClient.Write(ctx, &v1.StorageWriteRequest{ - BucketName: o.bucket, - Key: o.key, - Body: content, - }); err != nil { - return errors.FromGrpcError(err) - } - - return nil -} - -func (o *fileImpl) Delete(ctx context.Context) error { - if _, err := o.storageClient.Delete(ctx, &v1.StorageDeleteRequest{ - BucketName: o.bucket, - Key: o.key, - }); err != nil { - return errors.FromGrpcError(err) - } - - return nil -} - -type PresignUrlOptions struct { - Mode Mode - Expiry time.Duration -} - -func (p PresignUrlOptions) isValid() error { - if p.Mode != ModeRead && p.Mode != ModeWrite { - return fmt.Errorf("invalid mode: %d", p.Mode) - } - - return nil -} - -func (o *fileImpl) UploadUrl(ctx context.Context, expiry time.Duration) (string, error) { - return o.signUrl(ctx, PresignUrlOptions{Expiry: expiry, Mode: ModeWrite}) -} - -func (o *fileImpl) DownloadUrl(ctx context.Context, expiry time.Duration) (string, error) { - return o.signUrl(ctx, PresignUrlOptions{Expiry: expiry, Mode: ModeRead}) -} - -func (o *fileImpl) signUrl(ctx context.Context, opts PresignUrlOptions) (string, error) { - if err := opts.isValid(); err != nil { - return "", errors.NewWithCause(codes.InvalidArgument, "invalid options", err) - } - - op := v1.StoragePreSignUrlRequest_READ - - if opts.Mode == ModeWrite { - op = v1.StoragePreSignUrlRequest_WRITE - } - - r, err := o.storageClient.PreSignUrl(ctx, &v1.StoragePreSignUrlRequest{ - BucketName: o.bucket, - Key: o.key, - Operation: op, - Expiry: durationpb.New(opts.Expiry), - }) - if err != nil { - return "", errors.FromGrpcError(err) - } - - return r.Url, nil -} diff --git a/api/storage/file_test.go b/api/storage/file_test.go deleted file mode 100644 index 9f6dc23..0000000 --- a/api/storage/file_test.go +++ /dev/null @@ -1,499 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 storage - -import ( - "context" - "errors" - "strings" - "time" - - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/nitrictech/go-sdk/api/errors/codes" - mock_v1 "github.com/nitrictech/go-sdk/mocks" - v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" -) - -var _ = Describe("File", func() { - var ( - ctrl *gomock.Controller - mockStorage *mock_v1.MockStorageClient - bucket *bucketImpl - file File - bucketName string - fileName string - ctx context.Context - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockStorage = mock_v1.NewMockStorageClient(ctrl) - - bucketName = "test-bucket" - fileName = "test-file.txt" - - bucket = &bucketImpl{ - name: bucketName, - storageClient: mockStorage, - } - file = bucket.File(fileName) - - ctx = context.Background() - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Name()", func() { - It("should have the same file name as the one provided", func() { - _fileName := file.Name() - Expect(_fileName).To(Equal(fileName)) - }) - }) - - Describe("Read()", func() { - When("the gRPC Read operation is successful", func() { - var fileContent []byte - - BeforeEach(func() { - fileContent = []byte("this is dummy file content for testing") - - By("the gRPC server returning a successful response") - mockStorage.EXPECT().Read(gomock.Any(), &v1.StorageReadRequest{ - BucketName: bucketName, - Key: fileName, - }).Return(&v1.StorageReadResponse{ - Body: fileContent, - }, nil).Times(1) - }) - - It("should return the read bytes", func() { - fileData, err := file.Read(ctx) - - By("not returning any error") - Expect(err).ToNot(HaveOccurred()) - - By("returning the expected data in file") - Expect(fileData).To(Equal(fileContent)) - }) - }) - - When("the grpc server returns an error", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "Internal Error" - - By("the gRPC server returning an error") - mockStorage.EXPECT().Read(gomock.Any(), gomock.Any()).Return( - nil, - errors.New(errorMsg), - ).Times(1) - }) - - It("should return the passed error", func() { - fileData, err := file.Read(ctx) - - By("returning error with expected message") - Expect(err).To(HaveOccurred()) - Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - - By("returning nil as file data") - Expect(fileData).To(BeNil()) - }) - }) - }) - - Describe("Write", func() { - var fileData []byte - - BeforeEach(func() { - fileData = []byte("this is dummy file content for testing") - }) - - When("the gRPC write operation is successful", func() { - BeforeEach(func() { - By("the gRPC server returning a successful response") - mockStorage.EXPECT().Write(gomock.Any(), &v1.StorageWriteRequest{ - BucketName: bucketName, - Key: fileName, - Body: fileData, - }).Return( - &v1.StorageWriteResponse{}, - nil, - ).Times(1) - }) - - It("should not return an error", func() { - err := file.Write(ctx, fileData) - Expect(err).ToNot(HaveOccurred()) - }) - }) - - When("the grpc server returns an error", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "Internal Error" - - By("the gRPC server returning an error") - mockStorage.EXPECT().Write(gomock.Any(), gomock.Any()).Return( - nil, - errors.New(errorMsg), - ).Times(1) - }) - - It("should return the passed error", func() { - err := file.Write(ctx, fileData) - - By("returning error with expected message") - Expect(err).To(HaveOccurred()) - Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - }) - }) - }) - - Describe("Delete", func() { - When("the delete gRPC operation is successful", func() { - BeforeEach(func() { - By("the gRPC server returning a successful response") - mockStorage.EXPECT().Delete(gomock.Any(), gomock.Any()).Return( - &v1.StorageDeleteResponse{}, - nil, - ).Times(1) - }) - - It("should not return an error", func() { - err := file.Delete(ctx) - Expect(err).ToNot(HaveOccurred()) - }) - }) - - When("the grpc server returns an error", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "Internal Error" - - By("the gRPC server returning an error") - mockStorage.EXPECT().Delete(gomock.Any(), gomock.Any()).Return( - nil, - errors.New(errorMsg), - ).Times(1) - }) - - It("should pass through the returned error", func() { - err := file.Delete(ctx) - - By("returning error with expected message") - Expect(err).To(HaveOccurred()) - Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - }) - }) - }) - - Describe("UploadUrl()", func() { - var expiry time.Duration - - BeforeEach(func() { - expiry = 1 * time.Hour // 1 hour - }) - - When("the PreSignUrl gRPC operation is successful", func() { - var url string - - BeforeEach(func() { - url = "https://example.com" - - mockStorage.EXPECT().PreSignUrl(ctx, &v1.StoragePreSignUrlRequest{ - BucketName: bucketName, - Key: fileName, - Operation: v1.StoragePreSignUrlRequest_WRITE, - Expiry: durationpb.New(expiry), - }).Return(&v1.StoragePreSignUrlResponse{ - Url: url, - }, nil).Times(1) - }) - - It("should return a valid url stirng", func() { - _url, err := file.UploadUrl(ctx, expiry) - - By("not returning any errors") - Expect(err).ToNot(HaveOccurred()) - By("returning a valid url") - Expect(_url).To(Equal(url)) - }) - }) - - When("the grpc server returns an error", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "Internal Error" - - mockStorage.EXPECT().PreSignUrl(gomock.Any(), gomock.Any()).Return( - &v1.StoragePreSignUrlResponse{ - Url: "", - }, - errors.New(errorMsg), - ).Times(1) - }) - - It("should pass through the returned error", func() { - _url, err := file.UploadUrl(ctx, expiry) - - By("returning error with expected message") - Expect(err).To(HaveOccurred()) - Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - - By("returning empty string url") - Expect(_url).To(Equal("")) - }) - }) - }) - - Describe("DownloadUrl()", func() { - var expiry time.Duration - - BeforeEach(func() { - expiry = 1 * time.Hour // 1 hour - }) - - When("the PreSignUrl gRPC operation is successful", func() { - var url string - - BeforeEach(func() { - url = "https://example.com" - - mockStorage.EXPECT().PreSignUrl(ctx, &v1.StoragePreSignUrlRequest{ - BucketName: bucketName, - Key: fileName, - Operation: v1.StoragePreSignUrlRequest_READ, - Expiry: durationpb.New(expiry), - }).Return(&v1.StoragePreSignUrlResponse{ - Url: url, - }, nil).Times(1) - }) - - It("should return a valid url stirng", func() { - _url, err := file.DownloadUrl(ctx, expiry) - - By("not returning any errors") - Expect(err).ToNot(HaveOccurred()) - By("returning a valid url") - Expect(_url).To(Equal(url)) - }) - }) - - When("the grpc server returns an error", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "Internal Error" - - mockStorage.EXPECT().PreSignUrl(gomock.Any(), gomock.Any()).Return( - &v1.StoragePreSignUrlResponse{ - Url: "", - }, - errors.New(errorMsg), - ).Times(1) - }) - - It("should pass through the returned error", func() { - _url, err := file.DownloadUrl(ctx, expiry) - - By("returning error with expected message") - Expect(err).To(HaveOccurred()) - Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - - By("returning empty string url") - Expect(_url).To(Equal("")) - }) - }) - }) -}) - -var _ = Describe("fileImpl", func() { - var ( - ctrl *gomock.Controller - mockStorage *mock_v1.MockStorageClient - bucket *bucketImpl - file File - fileI *fileImpl - bucketName string - fileName string - ok bool - ctx context.Context - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockStorage = mock_v1.NewMockStorageClient(ctrl) - - bucketName = "test-bucket" - fileName = "test-file.txt" - - bucket = &bucketImpl{ - name: bucketName, - storageClient: mockStorage, - } - file = bucket.File(fileName) - - By("accessing fileImpl from file") - fileI, ok = file.(*fileImpl) - Expect(ok).To(BeTrue()) - - ctx = context.Background() - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("signUrl()", func() { - var expiry time.Duration - - BeforeEach(func() { - expiry = 1 * time.Hour // 1 hour - }) - - When("invalid mode is provided", func() { - It("should return an error", func() { - _, err := fileI.signUrl(ctx, PresignUrlOptions{ - Mode: 9999, // Invalid Mode - Expiry: expiry, - }) - Expect(err).Should(HaveOccurred()) - Expect(strings.Contains(err.Error(), codes.InvalidArgument.String())).To(BeTrue()) - }) - }) - - When("The grpc server returns an error", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "Internal Error" - - By("the gRPC server returning an error") - mockStorage.EXPECT().PreSignUrl(gomock.Any(), &v1.StoragePreSignUrlRequest{ - BucketName: bucketName, - Key: fileName, - Operation: v1.StoragePreSignUrlRequest_READ, - Expiry: durationpb.New(expiry), - }).Return(nil, errors.New(errorMsg)).Times(1) - }) - - It("should pass through the returned error", func() { - _url, err := fileI.signUrl(ctx, PresignUrlOptions{ - Mode: ModeRead, - Expiry: expiry, - }) - - By("returning error with expected message") - Expect(err).To(HaveOccurred()) - Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - - By("returning empty string url") - Expect(_url).To(Equal("")) - }) - }) - - When("the PreSignUrl operation is successful", func() { - var url string - var mode Mode - - BeforeEach(func() { - url = "http://example.com" - mode = ModeWrite - - mockStorage.EXPECT().PreSignUrl(gomock.Any(), &v1.StoragePreSignUrlRequest{ - BucketName: bucketName, - Key: fileName, - Operation: v1.StoragePreSignUrlRequest_WRITE, - Expiry: durationpb.New(expiry), - }).Return(&v1.StoragePreSignUrlResponse{ - Url: url, - }, nil) - }) - - It("should return a success response", func() { - _url, err := fileI.signUrl(ctx, PresignUrlOptions{Mode: mode, Expiry: expiry}) - - By("no error being returned") - Expect(err).ToNot(HaveOccurred()) - - By("return expected url string") - Expect(_url).To(Equal(url)) - }) - }) - }) -}) - -var _ = Describe("PresignUrlOptions", func() { - var mode Mode - var expiry time.Duration - var p *PresignUrlOptions - - Describe("isValid()", func() { - When("valid mode and expiry are passed", func() { - BeforeEach(func() { - expiry = 1 * time.Hour // 1 hour - mode = ModeRead - - p = &PresignUrlOptions{ - Mode: mode, - Expiry: expiry, - } - }) - - It("should not return an error", func() { - err := p.isValid() - Expect(err).ToNot(HaveOccurred()) - }) - }) - - When("invalid mode is passed", func() { - var errorMsg string - - BeforeEach(func() { - errorMsg = "invalid mode" - expiry = 1 * time.Hour // 1 hour - - p = &PresignUrlOptions{ - Mode: 7, - Expiry: expiry, - } - }) - - It("should return an error", func() { - err := p.isValid() - By("occurrence of error") - Expect(err).To(HaveOccurred()) - - By("containing appropriate error message") - Expect(strings.Contains( - strings.ToLower(err.Error()), - strings.ToLower(errorMsg), - ), - ).To(BeTrue()) - }) - }) - }) -}) diff --git a/api/storage/storage.go b/api/storage/storage.go deleted file mode 100644 index 927a556..0000000 --- a/api/storage/storage.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 storage - -import ( - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/constants" - v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" -) - -// Storage - Nitric storage API client -type Storage interface { - // Bucket - Get a bucket reference for the provided name - Bucket(name string) Bucket -} - -type storageImpl struct { - storageClient v1.StorageClient -} - -func (s *storageImpl) Bucket(name string) Bucket { - return &bucketImpl{ - storageClient: s.storageClient, - name: name, - } -} - -// New - Create a new Storage client with default options -func New() (Storage, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "Storage.New: Unable to reach StorageServiceServer", - err, - ) - } - - sClient := v1.NewStorageClient(conn) - - return &storageImpl{ - storageClient: sClient, - }, nil -} diff --git a/api/storage/storage_test.go b/api/storage/storage_test.go deleted file mode 100644 index 2ec9ac4..0000000 --- a/api/storage/storage_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 storage - -import ( - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - mock_v1 "github.com/nitrictech/go-sdk/mocks" -) - -var _ = Describe("Storage API", func() { - var ( - ctrl *gomock.Controller - mockStorage *mock_v1.MockStorageClient - s Storage - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockStorage = mock_v1.NewMockStorageClient(ctrl) - - s = &storageImpl{ - storageClient: mockStorage, - } - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Bucket()", func() { - var bucketName string - var bucketI *bucketImpl - var ok bool - - When("creating a new Bucket reference", func() { - BeforeEach(func() { - bucketName = "test-bucket" - bucket := s.Bucket(bucketName) - bucketI, ok = bucket.(*bucketImpl) - }) - - It("should return a bucketImpl instance", func() { - Expect(ok).To(BeTrue()) - }) - - It("should have the provied bucket name", func() { - Expect(bucketI.name).To(Equal(bucketName)) - }) - - It("should share the storage clients gRPC client", func() { - Expect(bucketI.storageClient).To(Equal(mockStorage)) - }) - }) - }) -}) diff --git a/api/topics/topics.go b/api/topics/topics.go deleted file mode 100644 index 4c95fc7..0000000 --- a/api/topics/topics.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 topics - -import ( - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/constants" - v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" -) - -// Topics -type Topics interface { - // Topic - Retrieve a Topic reference - Topic(name string) Topic -} - -type topicsImpl struct { - topicClient v1.TopicsClient -} - -func (s *topicsImpl) Topic(name string) Topic { - // Just return the straight topic reference - // we can fail if the topic does not exist - return &topicImpl{ - name: name, - topicClient: s.topicClient, - } -} - -// New - Construct a new Eventing Client with default options -func New() (Topics, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, errors.NewWithCause(codes.Unavailable, "Unable to dial Events service", err) - } - - tc := v1.NewTopicsClient(conn) - - return &topicsImpl{ - topicClient: tc, - }, nil -} diff --git a/api/topics/topics_test.go b/api/topics/topics_test.go deleted file mode 100644 index 52fefbb..0000000 --- a/api/topics/topics_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 topics - -import ( - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - mock_v1 "github.com/nitrictech/go-sdk/mocks" -) - -var _ = Describe("Topics API", func() { - var ( - ctrl *gomock.Controller - mockTopics *mock_v1.MockTopicsClient - ts Topics - ) - - BeforeEach(func() { - ctrl = gomock.NewController(GinkgoT()) - mockTopics = mock_v1.NewMockTopicsClient(ctrl) - - ts = &topicsImpl{ - topicClient: mockTopics, - } - }) - - AfterEach(func() { - ctrl.Finish() - }) - - Describe("Topic()", func() { - var topicName string - var topicI *topicImpl - var ok bool - - When("creating a new Topic reference", func() { - BeforeEach(func() { - topicName = "test-topic" - topic := ts.Topic(topicName) - topicI, ok = topic.(*topicImpl) - }) - - It("should return a topicImpl instance", func() { - Expect(ok).To(BeTrue()) - }) - - It("should have the provied topic name", func() { - Expect(topicI.name).To(Equal(topicName)) - }) - - It("should share the storage clients gRPC client", func() { - Expect(topicI.topicClient).To(Equal(mockTopics)) - }) - }) - }) -}) diff --git a/licenses.go b/licenses.go index 9c01561..7656872 100644 --- a/licenses.go +++ b/licenses.go @@ -18,12 +18,16 @@ package main // This main package is a workaround for binary license scanning that forces transitive dependencies in // Code we're distributing to be analyzed import ( - _ "github.com/nitrictech/go-sdk/api/keyvalue" - _ "github.com/nitrictech/go-sdk/api/queues" - _ "github.com/nitrictech/go-sdk/api/secrets" - _ "github.com/nitrictech/go-sdk/api/storage" - _ "github.com/nitrictech/go-sdk/api/topics" _ "github.com/nitrictech/go-sdk/nitric" + _ "github.com/nitrictech/go-sdk/nitric/apis" + _ "github.com/nitrictech/go-sdk/nitric/errors" + _ "github.com/nitrictech/go-sdk/nitric/keyvalue" + _ "github.com/nitrictech/go-sdk/nitric/queues" + _ "github.com/nitrictech/go-sdk/nitric/schedules" + _ "github.com/nitrictech/go-sdk/nitric/secrets" + _ "github.com/nitrictech/go-sdk/nitric/storage" + _ "github.com/nitrictech/go-sdk/nitric/topics" + _ "github.com/nitrictech/go-sdk/nitric/websockets" ) func main() {} diff --git a/mocks/mockapi/keyvalue.go b/mocks/mockapi/keyvalue.go deleted file mode 100644 index b393f22..0000000 --- a/mocks/mockapi/keyvalue.go +++ /dev/null @@ -1,151 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nitrictech/go-sdk/api/keyvalue (interfaces: KeyValue,Store) - -// Package mockapi is a generated GoMock package. -package mockapi - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - keyvalue "github.com/nitrictech/go-sdk/api/keyvalue" - kvstorepb "github.com/nitrictech/nitric/core/pkg/proto/kvstore/v1" -) - -// MockKeyValue is a mock of KeyValue interface. -type MockKeyValue struct { - ctrl *gomock.Controller - recorder *MockKeyValueMockRecorder -} - -// MockKeyValueMockRecorder is the mock recorder for MockKeyValue. -type MockKeyValueMockRecorder struct { - mock *MockKeyValue -} - -// NewMockKeyValue creates a new mock instance. -func NewMockKeyValue(ctrl *gomock.Controller) *MockKeyValue { - mock := &MockKeyValue{ctrl: ctrl} - mock.recorder = &MockKeyValueMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockKeyValue) EXPECT() *MockKeyValueMockRecorder { - return m.recorder -} - -// Store mocks base method. -func (m *MockKeyValue) Store(arg0 string) keyvalue.Store { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Store", arg0) - ret0, _ := ret[0].(keyvalue.Store) - return ret0 -} - -// Store indicates an expected call of Store. -func (mr *MockKeyValueMockRecorder) Store(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Store", reflect.TypeOf((*MockKeyValue)(nil).Store), arg0) -} - -// MockStore is a mock of Store interface. -type MockStore struct { - ctrl *gomock.Controller - recorder *MockStoreMockRecorder -} - -// MockStoreMockRecorder is the mock recorder for MockStore. -type MockStoreMockRecorder struct { - mock *MockStore -} - -// NewMockStore creates a new mock instance. -func NewMockStore(ctrl *gomock.Controller) *MockStore { - mock := &MockStore{ctrl: ctrl} - mock.recorder = &MockStoreMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockStore) EXPECT() *MockStoreMockRecorder { - return m.recorder -} - -// Delete mocks base method. -func (m *MockStore) Delete(arg0 context.Context, arg1 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// Delete indicates an expected call of Delete. -func (mr *MockStoreMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockStore)(nil).Delete), arg0, arg1) -} - -// Get mocks base method. -func (m *MockStore) Get(arg0 context.Context, arg1 string) (map[string]interface{}, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", arg0, arg1) - ret0, _ := ret[0].(map[string]interface{}) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockStoreMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockStore)(nil).Get), arg0, arg1) -} - -// Keys mocks base method. -func (m *MockStore) Keys(arg0 context.Context, arg1 ...func(*kvstorepb.KvStoreScanKeysRequest)) (*keyvalue.KeyStream, error) { - m.ctrl.T.Helper() - varargs := []interface{}{arg0} - for _, a := range arg1 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Keys", varargs...) - ret0, _ := ret[0].(*keyvalue.KeyStream) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Keys indicates an expected call of Keys. -func (mr *MockStoreMockRecorder) Keys(arg0 interface{}, arg1 ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0}, arg1...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Keys", reflect.TypeOf((*MockStore)(nil).Keys), varargs...) -} - -// Name mocks base method. -func (m *MockStore) Name() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Name") - ret0, _ := ret[0].(string) - return ret0 -} - -// Name indicates an expected call of Name. -func (mr *MockStoreMockRecorder) Name() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockStore)(nil).Name)) -} - -// Set mocks base method. -func (m *MockStore) Set(arg0 context.Context, arg1 string, arg2 map[string]interface{}) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Set", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// Set indicates an expected call of Set. -func (mr *MockStoreMockRecorder) Set(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockStore)(nil).Set), arg0, arg1, arg2) -} diff --git a/mocks/mockapi/queues.go b/mocks/mockapi/queues.go deleted file mode 100644 index 0d97d55..0000000 --- a/mocks/mockapi/queues.go +++ /dev/null @@ -1,117 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nitrictech/go-sdk/api/queues (interfaces: Queues,Queue) - -// Package mockapi is a generated GoMock package. -package mockapi - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - queues "github.com/nitrictech/go-sdk/api/queues" -) - -// MockQueues is a mock of Queues interface. -type MockQueues struct { - ctrl *gomock.Controller - recorder *MockQueuesMockRecorder -} - -// MockQueuesMockRecorder is the mock recorder for MockQueues. -type MockQueuesMockRecorder struct { - mock *MockQueues -} - -// NewMockQueues creates a new mock instance. -func NewMockQueues(ctrl *gomock.Controller) *MockQueues { - mock := &MockQueues{ctrl: ctrl} - mock.recorder = &MockQueuesMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockQueues) EXPECT() *MockQueuesMockRecorder { - return m.recorder -} - -// Queue mocks base method. -func (m *MockQueues) Queue(arg0 string) queues.Queue { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Queue", arg0) - ret0, _ := ret[0].(queues.Queue) - return ret0 -} - -// Queue indicates an expected call of Queue. -func (mr *MockQueuesMockRecorder) Queue(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Queue", reflect.TypeOf((*MockQueues)(nil).Queue), arg0) -} - -// MockQueue is a mock of Queue interface. -type MockQueue struct { - ctrl *gomock.Controller - recorder *MockQueueMockRecorder -} - -// MockQueueMockRecorder is the mock recorder for MockQueue. -type MockQueueMockRecorder struct { - mock *MockQueue -} - -// NewMockQueue creates a new mock instance. -func NewMockQueue(ctrl *gomock.Controller) *MockQueue { - mock := &MockQueue{ctrl: ctrl} - mock.recorder = &MockQueueMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockQueue) EXPECT() *MockQueueMockRecorder { - return m.recorder -} - -// Dequeue mocks base method. -func (m *MockQueue) Dequeue(arg0 context.Context, arg1 int) ([]queues.ReceivedMessage, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Dequeue", arg0, arg1) - ret0, _ := ret[0].([]queues.ReceivedMessage) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Dequeue indicates an expected call of Dequeue. -func (mr *MockQueueMockRecorder) Dequeue(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Dequeue", reflect.TypeOf((*MockQueue)(nil).Dequeue), arg0, arg1) -} - -// Enqueue mocks base method. -func (m *MockQueue) Enqueue(arg0 context.Context, arg1 []map[string]interface{}) ([]*queues.FailedMessage, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Enqueue", arg0, arg1) - ret0, _ := ret[0].([]*queues.FailedMessage) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Enqueue indicates an expected call of Enqueue. -func (mr *MockQueueMockRecorder) Enqueue(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Enqueue", reflect.TypeOf((*MockQueue)(nil).Enqueue), arg0, arg1) -} - -// Name mocks base method. -func (m *MockQueue) Name() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Name") - ret0, _ := ret[0].(string) - return ret0 -} - -// Name indicates an expected call of Name. -func (mr *MockQueueMockRecorder) Name() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockQueue)(nil).Name)) -} diff --git a/mocks/mockapi/secrets.go b/mocks/mockapi/secrets.go deleted file mode 100644 index 381550c..0000000 --- a/mocks/mockapi/secrets.go +++ /dev/null @@ -1,130 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nitrictech/go-sdk/api/secrets (interfaces: Secrets,SecretRef) - -// Package mockapi is a generated GoMock package. -package mockapi - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - secrets "github.com/nitrictech/go-sdk/api/secrets" -) - -// MockSecrets is a mock of Secrets interface. -type MockSecrets struct { - ctrl *gomock.Controller - recorder *MockSecretsMockRecorder -} - -// MockSecretsMockRecorder is the mock recorder for MockSecrets. -type MockSecretsMockRecorder struct { - mock *MockSecrets -} - -// NewMockSecrets creates a new mock instance. -func NewMockSecrets(ctrl *gomock.Controller) *MockSecrets { - mock := &MockSecrets{ctrl: ctrl} - mock.recorder = &MockSecretsMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockSecrets) EXPECT() *MockSecretsMockRecorder { - return m.recorder -} - -// Secret mocks base method. -func (m *MockSecrets) Secret(arg0 string) secrets.SecretRef { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Secret", arg0) - ret0, _ := ret[0].(secrets.SecretRef) - return ret0 -} - -// Secret indicates an expected call of Secret. -func (mr *MockSecretsMockRecorder) Secret(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Secret", reflect.TypeOf((*MockSecrets)(nil).Secret), arg0) -} - -// MockSecretRef is a mock of SecretRef interface. -type MockSecretRef struct { - ctrl *gomock.Controller - recorder *MockSecretRefMockRecorder -} - -// MockSecretRefMockRecorder is the mock recorder for MockSecretRef. -type MockSecretRefMockRecorder struct { - mock *MockSecretRef -} - -// NewMockSecretRef creates a new mock instance. -func NewMockSecretRef(ctrl *gomock.Controller) *MockSecretRef { - mock := &MockSecretRef{ctrl: ctrl} - mock.recorder = &MockSecretRefMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockSecretRef) EXPECT() *MockSecretRefMockRecorder { - return m.recorder -} - -// Latest mocks base method. -func (m *MockSecretRef) Latest() secrets.SecretVersionRef { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Latest") - ret0, _ := ret[0].(secrets.SecretVersionRef) - return ret0 -} - -// Latest indicates an expected call of Latest. -func (mr *MockSecretRefMockRecorder) Latest() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Latest", reflect.TypeOf((*MockSecretRef)(nil).Latest)) -} - -// Name mocks base method. -func (m *MockSecretRef) Name() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Name") - ret0, _ := ret[0].(string) - return ret0 -} - -// Name indicates an expected call of Name. -func (mr *MockSecretRefMockRecorder) Name() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockSecretRef)(nil).Name)) -} - -// Put mocks base method. -func (m *MockSecretRef) Put(arg0 context.Context, arg1 []byte) (secrets.SecretVersionRef, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Put", arg0, arg1) - ret0, _ := ret[0].(secrets.SecretVersionRef) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Put indicates an expected call of Put. -func (mr *MockSecretRefMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockSecretRef)(nil).Put), arg0, arg1) -} - -// Version mocks base method. -func (m *MockSecretRef) Version(arg0 string) secrets.SecretVersionRef { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Version", arg0) - ret0, _ := ret[0].(secrets.SecretVersionRef) - return ret0 -} - -// Version indicates an expected call of Version. -func (mr *MockSecretRefMockRecorder) Version(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Version", reflect.TypeOf((*MockSecretRef)(nil).Version), arg0) -} diff --git a/mocks/mockapi/storage.go b/mocks/mockapi/storage.go deleted file mode 100644 index 0b77856..0000000 --- a/mocks/mockapi/storage.go +++ /dev/null @@ -1,116 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nitrictech/go-sdk/api/storage (interfaces: Storage,Bucket) - -// Package mockapi is a generated GoMock package. -package mockapi - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - storage "github.com/nitrictech/go-sdk/api/storage" -) - -// MockStorage is a mock of Storage interface. -type MockStorage struct { - ctrl *gomock.Controller - recorder *MockStorageMockRecorder -} - -// MockStorageMockRecorder is the mock recorder for MockStorage. -type MockStorageMockRecorder struct { - mock *MockStorage -} - -// NewMockStorage creates a new mock instance. -func NewMockStorage(ctrl *gomock.Controller) *MockStorage { - mock := &MockStorage{ctrl: ctrl} - mock.recorder = &MockStorageMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockStorage) EXPECT() *MockStorageMockRecorder { - return m.recorder -} - -// Bucket mocks base method. -func (m *MockStorage) Bucket(arg0 string) storage.Bucket { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Bucket", arg0) - ret0, _ := ret[0].(storage.Bucket) - return ret0 -} - -// Bucket indicates an expected call of Bucket. -func (mr *MockStorageMockRecorder) Bucket(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bucket", reflect.TypeOf((*MockStorage)(nil).Bucket), arg0) -} - -// MockBucket is a mock of Bucket interface. -type MockBucket struct { - ctrl *gomock.Controller - recorder *MockBucketMockRecorder -} - -// MockBucketMockRecorder is the mock recorder for MockBucket. -type MockBucketMockRecorder struct { - mock *MockBucket -} - -// NewMockBucket creates a new mock instance. -func NewMockBucket(ctrl *gomock.Controller) *MockBucket { - mock := &MockBucket{ctrl: ctrl} - mock.recorder = &MockBucketMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockBucket) EXPECT() *MockBucketMockRecorder { - return m.recorder -} - -// File mocks base method. -func (m *MockBucket) File(arg0 string) storage.File { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "File", arg0) - ret0, _ := ret[0].(storage.File) - return ret0 -} - -// File indicates an expected call of File. -func (mr *MockBucketMockRecorder) File(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "File", reflect.TypeOf((*MockBucket)(nil).File), arg0) -} - -// Files mocks base method. -func (m *MockBucket) Files(arg0 context.Context) ([]storage.File, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Files", arg0) - ret0, _ := ret[0].([]storage.File) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Files indicates an expected call of Files. -func (mr *MockBucketMockRecorder) Files(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Files", reflect.TypeOf((*MockBucket)(nil).Files), arg0) -} - -// Name mocks base method. -func (m *MockBucket) Name() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Name") - ret0, _ := ret[0].(string) - return ret0 -} - -// Name indicates an expected call of Name. -func (mr *MockBucketMockRecorder) Name() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockBucket)(nil).Name)) -} diff --git a/mocks/mockapi/topics.go b/mocks/mockapi/topics.go deleted file mode 100644 index ee0a470..0000000 --- a/mocks/mockapi/topics.go +++ /dev/null @@ -1,107 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nitrictech/go-sdk/api/topics (interfaces: Topics,Topic) - -// Package mockapi is a generated GoMock package. -package mockapi - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - topics "github.com/nitrictech/go-sdk/api/topics" - topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" -) - -// MockTopics is a mock of Topics interface. -type MockTopics struct { - ctrl *gomock.Controller - recorder *MockTopicsMockRecorder -} - -// MockTopicsMockRecorder is the mock recorder for MockTopics. -type MockTopicsMockRecorder struct { - mock *MockTopics -} - -// NewMockTopics creates a new mock instance. -func NewMockTopics(ctrl *gomock.Controller) *MockTopics { - mock := &MockTopics{ctrl: ctrl} - mock.recorder = &MockTopicsMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockTopics) EXPECT() *MockTopicsMockRecorder { - return m.recorder -} - -// Topic mocks base method. -func (m *MockTopics) Topic(arg0 string) topics.Topic { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Topic", arg0) - ret0, _ := ret[0].(topics.Topic) - return ret0 -} - -// Topic indicates an expected call of Topic. -func (mr *MockTopicsMockRecorder) Topic(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Topic", reflect.TypeOf((*MockTopics)(nil).Topic), arg0) -} - -// MockTopic is a mock of Topic interface. -type MockTopic struct { - ctrl *gomock.Controller - recorder *MockTopicMockRecorder -} - -// MockTopicMockRecorder is the mock recorder for MockTopic. -type MockTopicMockRecorder struct { - mock *MockTopic -} - -// NewMockTopic creates a new mock instance. -func NewMockTopic(ctrl *gomock.Controller) *MockTopic { - mock := &MockTopic{ctrl: ctrl} - mock.recorder = &MockTopicMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockTopic) EXPECT() *MockTopicMockRecorder { - return m.recorder -} - -// Name mocks base method. -func (m *MockTopic) Name() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Name") - ret0, _ := ret[0].(string) - return ret0 -} - -// Name indicates an expected call of Name. -func (mr *MockTopicMockRecorder) Name() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockTopic)(nil).Name)) -} - -// Publish mocks base method. -func (m *MockTopic) Publish(arg0 context.Context, arg1 map[string]interface{}, arg2 ...func(*topicspb.TopicPublishRequest)) error { - m.ctrl.T.Helper() - varargs := []interface{}{arg0, arg1} - for _, a := range arg2 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Publish", varargs...) - ret0, _ := ret[0].(error) - return ret0 -} - -// Publish indicates an expected call of Publish. -func (mr *MockTopicMockRecorder) Publish(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0, arg1}, arg2...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockTopic)(nil).Publish), varargs...) -} diff --git a/nitric/api.go b/nitric/api.go index 958665b..dd2343d 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -19,7 +19,7 @@ import ( "path" "strings" - httpx "github.com/nitrictech/go-sdk/api/apis" + httpx "github.com/nitrictech/go-sdk/nitric/apis" apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" resourcev1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" @@ -27,13 +27,21 @@ import ( // Route providers convenience functions to register a handler in a single method. type Route interface { + // All adds a handler for all HTTP methods to the route. All(handler interface{}, opts ...MethodOption) + // Get adds a Get method handler to the route. Get(handler interface{}, opts ...MethodOption) + // Put adds a Put method handler to the route. Patch(handler interface{}, opts ...MethodOption) + // Patch adds a Patch method handler to the route. Put(handler interface{}, opts ...MethodOption) + // Post adds a Post method handler to the route. Post(handler interface{}, opts ...MethodOption) + // Delete adds a Delete method handler to the route. Delete(handler interface{}, opts ...MethodOption) + // Options adds an Options method handler to the route. Options(handler interface{}, opts ...MethodOption) + // ApiName returns the name of the API this route belongs to. ApiName() string } @@ -41,7 +49,7 @@ type route struct { path string api *api middleware Middleware[httpx.Ctx] - manager Manager + manager *manager } func composeRouteMiddleware(apiMiddleware Middleware[httpx.Ctx], routeMiddleware []Middleware[httpx.Ctx]) Middleware[httpx.Ctx] { @@ -247,6 +255,7 @@ type Api interface { // Middleware[apis.Ctx] // Handler[apis.Ctx] Options(path string, handler interface{}, opts ...MethodOption) + // NewRoute creates a new Route object for the given path. NewRoute(path string, middleware ...Middleware[httpx.Ctx]) Route } @@ -258,7 +267,7 @@ type ApiDetails struct { type api struct { name string routes map[string]Route - manager Manager + manager *manager securityRules map[string]interface{} security []OidcOptions path string diff --git a/nitric/api_test.go b/nitric/api_test.go deleted file mode 100644 index f3a5cc5..0000000 --- a/nitric/api_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -// import ( -// "context" - -// "github.com/golang/mock/gomock" -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" - -// "github.com/nitrictech/go-sdk/faas" -// mock_v1 "github.com/nitrictech/go-sdk/mocks" -// v1 "github.com/nitrictech/nitric/core/pkg/api/nitric/v1" -// ) - -// var _ = Describe("api", func() { -// Context("New", func() { -// It("can register one method per routes", func() { -// m := &manager{ -// workers: map[string]Starter{}, -// builders: map[string]faas.HandlerBuilder{}, -// } -// a := &api{ -// name: "testApi", -// routes: map[string]Route{}, -// manager: m, -// } -// a.Get("objects/", func(hc *faas.HttpContext, hh faas.HttpHandler) (*faas.HttpContext, error) { return hc, nil }) -// a.Post("objects/", func(hc *faas.HttpContext, hh faas.HttpHandler) (*faas.HttpContext, error) { return hc, nil }) -// a.Get("objects/:id", func(hc *faas.HttpContext, hh faas.HttpHandler) (*faas.HttpContext, error) { return hc, nil }) -// a.Put("objects/:id", func(hc *faas.HttpContext, hh faas.HttpHandler) (*faas.HttpContext, error) { return hc, nil }) -// a.Patch("objects/:id", func(hc *faas.HttpContext, hh faas.HttpHandler) (*faas.HttpContext, error) { return hc, nil }) -// a.Delete("objects/:id", func(hc *faas.HttpContext, hh faas.HttpHandler) (*faas.HttpContext, error) { return hc, nil }) -// a.Options("objects/:id", func(hc *faas.HttpContext, hh faas.HttpHandler) (*faas.HttpContext, error) { return hc, nil }) - -// Expect(m.workers["route:testApi/objects/GET"]).ToNot(BeNil()) -// Expect(m.workers["route:testApi/objects/POST"]).ToNot(BeNil()) -// Expect(m.workers["route:testApi/objects/:id/GET"]).ToNot(BeNil()) -// Expect(m.workers["route:testApi/objects/:id/PUT"]).ToNot(BeNil()) -// Expect(m.workers["route:testApi/objects/:id/DELETE"]).ToNot(BeNil()) -// Expect(m.workers["route:testApi/objects/:id/OPTIONS"]).ToNot(BeNil()) -// }) -// It("can get api details", func() { -// ctrl := gomock.NewController(GinkgoT()) -// mockClient := mock_v1.NewMockResourceServiceClient(ctrl) -// mockConn := mock_v1.NewMockClientConnInterface(ctrl) -// m := &manager{ -// workers: map[string]Starter{}, -// builders: map[string]faas.HandlerBuilder{}, -// rsc: mockClient, -// conn: mockConn, -// } - -// mockClient.EXPECT().Details(gomock.Any(), &v1.ResourceDetailsRequest{ -// Resource: &v1.Resource{ -// Name: "testApi", -// Type: v1.ResourceType_Api, -// }, -// }).Return(&v1.ResourceDetailsResponse{ -// Id: "1234", -// Provider: "aws", -// Service: "lambda", -// Details: &v1.ResourceDetailsResponse_Api{ -// Api: &v1.ApiResourceDetails{ -// Url: "example.com/aws/thing", -// }, -// }, -// }, nil) -// a := &api{ -// name: "testApi", -// routes: map[string]Route{}, -// manager: m, -// } -// ad, err := a.Details(context.TODO()) -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(ad).To(Equal(&ApiDetails{ -// Details: Details{ -// ID: "1234", -// Provider: "aws", -// Service: "lambda", -// }, -// URL: "example.com/aws/thing", -// })) -// }) -// }) - -// Context("New With Security", func() { -// It("declares a new API resource with security rules", func() { -// ctrl := gomock.NewController(GinkgoT()) -// mockClient := mock_v1.NewMockResourceServiceClient(ctrl) -// mockConn := mock_v1.NewMockClientConnInterface(ctrl) -// m := &manager{ -// workers: map[string]Starter{}, -// builders: map[string]faas.HandlerBuilder{}, -// rsc: mockClient, -// conn: mockConn, -// } - -// mockClient.EXPECT().Declare(context.TODO(), &v1.ResourceDeclareRequest{ -// Resource: &v1.Resource{ -// Type: v1.ResourceType_Api, -// Name: "testApi", -// }, Config: &v1.ResourceDeclareRequest_Api{ -// Api: &v1.ApiResource{ -// SecurityDefinitions: map[string]*v1.ApiSecurityDefinition{ -// "jwt": { -// Definition: &v1.ApiSecurityDefinition_Jwt{ -// Jwt: &v1.ApiSecurityDefinitionJwt{ -// Audiences: []string{"test"}, -// Issuer: "https://test.com", -// }, -// }, -// }, -// }, -// Security: map[string]*v1.ApiScopes{ -// "jwt": { -// Scopes: []string{}, -// }, -// }, -// }, -// }, -// }).Times(1) - -// a, err := m.newApi("testApi", WithSecurityJwtRule("jwt", JwtSecurityRule{ -// Audiences: []string{"test"}, -// Issuer: "https://test.com", -// }), WithSecurity("jwt", []string{})) - -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(a).ToNot(BeNil()) - -// ctrl.Finish() -// }) -// }) -// }) diff --git a/nitric/api_workers.go b/nitric/api_workers.go index 397379c..5b70d86 100644 --- a/nitric/api_workers.go +++ b/nitric/api_workers.go @@ -21,10 +21,10 @@ import ( "google.golang.org/grpc" - httpx "github.com/nitrictech/go-sdk/api/apis" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" "github.com/nitrictech/go-sdk/constants" + httpx "github.com/nitrictech/go-sdk/nitric/apis" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" ) diff --git a/api/apis/context.go b/nitric/apis/context.go similarity index 98% rename from api/apis/context.go rename to nitric/apis/context.go index ecaef24..de0d499 100644 --- a/api/apis/context.go +++ b/nitric/apis/context.go @@ -58,7 +58,7 @@ func NewCtx(msg *apispb.ServerMessage) *Ctx { return &Ctx{ id: msg.Id, - Request: &RequestImpl{ + Request: &HttpRequest{ method: req.Method, path: req.Path, pathParams: req.PathParams, diff --git a/api/apis/request.go b/nitric/apis/request.go similarity index 77% rename from api/apis/request.go rename to nitric/apis/request.go index 500c601..5d3f458 100644 --- a/api/apis/request.go +++ b/nitric/apis/request.go @@ -23,7 +23,7 @@ type Request interface { PathParams() map[string]string } -type RequestImpl struct { +type HttpRequest struct { method string path string data []byte @@ -32,26 +32,26 @@ type RequestImpl struct { pathParams map[string]string } -func (h *RequestImpl) Method() string { +func (h *HttpRequest) Method() string { return h.method } -func (h *RequestImpl) Path() string { +func (h *HttpRequest) Path() string { return h.path } -func (h *RequestImpl) Data() []byte { +func (h *HttpRequest) Data() []byte { return h.data } -func (h *RequestImpl) Query() map[string][]string { +func (h *HttpRequest) Query() map[string][]string { return h.query } -func (h *RequestImpl) Headers() map[string][]string { +func (h *HttpRequest) Headers() map[string][]string { return h.headers } -func (h *RequestImpl) PathParams() map[string]string { +func (h *HttpRequest) PathParams() map[string]string { return h.pathParams } diff --git a/api/apis/response.go b/nitric/apis/response.go similarity index 100% rename from api/apis/response.go rename to nitric/apis/response.go diff --git a/nitric/bucket.go b/nitric/bucket.go index 0d6fc02..4a537ec 100644 --- a/nitric/bucket.go +++ b/nitric/bucket.go @@ -18,7 +18,7 @@ import ( "fmt" "strings" - "github.com/nitrictech/go-sdk/api/storage" + "github.com/nitrictech/go-sdk/nitric/storage" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" storagepb "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" ) @@ -27,12 +27,13 @@ type BucketPermission string type bucket struct { name string - manager Manager + manager *manager registerChan <-chan RegisterResult } type Bucket interface { - Allow(BucketPermission, ...BucketPermission) (storage.Bucket, error) + // Allow requests the given permissions to the bucket. + Allow(BucketPermission, ...BucketPermission) (*storage.Bucket, error) // On registers a handler for a specific event type on the bucket. // Valid function signatures for middleware are: @@ -59,8 +60,7 @@ const ( var BucketEverything []BucketPermission = []BucketPermission{BucketRead, BucketWrite, BucketDelete} -// NewBucket register this bucket as a required resource for the calling function/container and -// register the permissions required by the currently scoped function for this resource. +// NewBucket - Create a new Bucket resource func NewBucket(name string) Bucket { bucket := &bucket{ name: name, @@ -80,7 +80,7 @@ func NewBucket(name string) Bucket { return bucket } -func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) (storage.Bucket, error) { +func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) (*storage.Bucket, error) { allPerms := append([]BucketPermission{permission}, permissions...) actions := []v1.Action{} @@ -102,19 +102,12 @@ func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermiss return nil, registerResult.Err } - m, err := b.manager.registerPolicy(registerResult.Identifier, actions...) + err := b.manager.registerPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - if m.storage == nil { - m.storage, err = storage.New() - if err != nil { - return nil, err - } - } - - return m.storage.Bucket(b.name), nil + return storage.NewBucket(b.name) } func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter string, middleware ...interface{}) { diff --git a/nitric/bucket_test.go b/nitric/bucket_test.go deleted file mode 100644 index d320751..0000000 --- a/nitric/bucket_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -// import ( -// "context" - -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" - -// "github.com/golang/mock/gomock" - -// mock_v1 "github.com/nitrictech/go-sdk/mocks" -// "github.com/nitrictech/go-sdk/mocks/mockapi" -// v1 "github.com/nitrictech/nitric/core/pkg/api/nitric/v1" -// ) - -// var _ = Describe("bucket", func() { -// ctrl := gomock.NewController(GinkgoT()) -// Context("New", func() { -// mockConn := mock_v1.NewMockClientConnInterface(ctrl) -// When("valid args", func() { -// mockClient := mock_v1.NewMockResourceServiceClient(ctrl) -// mockStorage := mockapi.NewMockStorage(ctrl) - -// m := &manager{ -// workers: map[string]Starter{}, -// conn: mockConn, -// rsc: mockClient, -// storage: mockStorage, -// } - -// mockClient.EXPECT().Declare(context.Background(), -// &v1.ResourceDeclareRequest{ -// Resource: &v1.Resource{ -// Type: v1.ResourceType_Bucket, -// Name: "red", -// }, -// Config: &v1.ResourceDeclareRequest_Bucket{ -// Bucket: &v1.BucketResource{}, -// }, -// }) - -// mockClient.EXPECT().Declare(context.Background(), -// &v1.ResourceDeclareRequest{ -// Resource: &v1.Resource{ -// Type: v1.ResourceType_Policy, -// }, -// Config: &v1.ResourceDeclareRequest_Policy{ -// Policy: &v1.PolicyResource{ -// Principals: []*v1.Resource{{ -// Type: v1.ResourceType_Function, -// }}, -// Actions: []v1.Action{ -// v1.Action_BucketFileGet, v1.Action_BucketFileList, v1.Action_BucketFilePut, -// }, -// Resources: []*v1.Resource{{ -// Type: v1.ResourceType_Bucket, -// Name: "red", -// }}, -// }, -// }, -// }) - -// mockBucket := mockapi.NewMockBucket(ctrl) -// mockStorage.EXPECT().Bucket("red").Return(mockBucket) -// b, err := m.newBucket("red", BucketReading, BucketWriting) - -// It("should not return an error", func() { -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(b).ShouldNot(BeNil()) -// }) -// }) -// }) -// }) diff --git a/nitric/bucket_workers.go b/nitric/bucket_workers.go index 0220add..a5634e6 100644 --- a/nitric/bucket_workers.go +++ b/nitric/bucket_workers.go @@ -21,10 +21,10 @@ import ( "google.golang.org/grpc" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/api/storage" "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + "github.com/nitrictech/go-sdk/nitric/storage" v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" ) diff --git a/api/errors/api_error.go b/nitric/errors/api_error.go similarity index 97% rename from api/errors/api_error.go rename to nitric/errors/api_error.go index d583812..c688d2c 100644 --- a/api/errors/api_error.go +++ b/nitric/errors/api_error.go @@ -21,7 +21,7 @@ import ( multierror "github.com/missionMeteora/toolkit/errors" "google.golang.org/grpc/status" - "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/nitric/errors/codes" ) type ApiError struct { diff --git a/api/errors/codes/codes.go b/nitric/errors/codes/codes.go similarity index 100% rename from api/errors/codes/codes.go rename to nitric/errors/codes/codes.go diff --git a/nitric/keyvalue.go b/nitric/keyvalue.go index 4ddffce..885318c 100644 --- a/nitric/keyvalue.go +++ b/nitric/keyvalue.go @@ -17,7 +17,7 @@ package nitric import ( "fmt" - "github.com/nitrictech/go-sdk/api/keyvalue" + "github.com/nitrictech/go-sdk/nitric/keyvalue" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) @@ -32,15 +32,17 @@ const ( var KvStoreEverything []KvStorePermission = []KvStorePermission{KvStoreSet, KvStoreGet, KvStoreDelete} type KvStore interface { - Allow(KvStorePermission, ...KvStorePermission) (keyvalue.Store, error) + // Allow requests the given permissions to the key/value store. + Allow(KvStorePermission, ...KvStorePermission) (keyvalue.KvStoreClientIface, error) } type kvstore struct { name string - manager Manager + manager *manager registerChan <-chan RegisterResult } +// NewKv - Create a new Key/Value store resource func NewKv(name string) *kvstore { kvstore := &kvstore{ name: name, @@ -61,8 +63,7 @@ func NewKv(name string) *kvstore { return kvstore } -// NewQueue registers this queue as a required resource for the calling function/container. -func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePermission) (keyvalue.Store, error) { +func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePermission) (keyvalue.KvStoreClientIface, error) { allPerms := append([]KvStorePermission{permission}, permissions...) actions := []v1.Action{} @@ -85,17 +86,10 @@ func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePerm return nil, registerResult.Err } - m, err := k.manager.registerPolicy(registerResult.Identifier, actions...) + err := k.manager.registerPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - if m.kvstores == nil { - m.kvstores, err = keyvalue.New() - if err != nil { - return nil, err - } - } - - return m.kvstores.Store(k.name), nil + return keyvalue.NewKvStoreClient(k.name) } diff --git a/api/keyvalue/keyvalue_suite_test.go b/nitric/keyvalue/keyvalue_suite_test.go similarity index 100% rename from api/keyvalue/keyvalue_suite_test.go rename to nitric/keyvalue/keyvalue_suite_test.go diff --git a/api/keyvalue/store.go b/nitric/keyvalue/store.go similarity index 75% rename from api/keyvalue/store.go rename to nitric/keyvalue/store.go index e745297..eea2a77 100644 --- a/api/keyvalue/store.go +++ b/nitric/keyvalue/store.go @@ -17,9 +17,11 @@ package keyvalue import ( "context" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/protoutils" + "google.golang.org/grpc" v1 "github.com/nitrictech/nitric/core/pkg/proto/kvstore/v1" ) @@ -49,7 +51,7 @@ func (k *KeyStream) Recv() (string, error) { return resp.Key, nil } -type Store interface { +type KvStoreClientIface interface { // Name - The name of the store Name() string // Get a value from the store @@ -62,16 +64,16 @@ type Store interface { Keys(context.Context, ...ScanKeysOption) (*KeyStream, error) } -type storeImpl struct { +type KvStoreClient struct { name string kvClient v1.KvStoreClient } -func (s *storeImpl) Name() string { +func (s *KvStoreClient) Name() string { return s.name } -func (s *storeImpl) Get(ctx context.Context, key string) (map[string]interface{}, error) { +func (s *KvStoreClient) Get(ctx context.Context, key string) (map[string]interface{}, error) { ref := &v1.ValueRef{ Store: s.name, Key: key, @@ -93,7 +95,7 @@ func (s *storeImpl) Get(ctx context.Context, key string) (map[string]interface{} return content, nil } -func (s *storeImpl) Set(ctx context.Context, key string, value map[string]interface{}) error { +func (s *KvStoreClient) Set(ctx context.Context, key string, value map[string]interface{}) error { ref := &v1.ValueRef{ Store: s.name, Key: key, @@ -116,7 +118,7 @@ func (s *storeImpl) Set(ctx context.Context, key string, value map[string]interf return nil } -func (s *storeImpl) Delete(ctx context.Context, key string) error { +func (s *KvStoreClient) Delete(ctx context.Context, key string) error { ref := &v1.ValueRef{ Store: s.name, Key: key, @@ -132,7 +134,7 @@ func (s *storeImpl) Delete(ctx context.Context, key string) error { return nil } -func (s *storeImpl) Keys(ctx context.Context, opts ...ScanKeysOption) (*KeyStream, error) { +func (s *KvStoreClient) Keys(ctx context.Context, opts ...ScanKeysOption) (*KeyStream, error) { store := &v1.Store{ Name: s.name, } @@ -156,3 +158,21 @@ func (s *storeImpl) Keys(ctx context.Context, opts ...ScanKeysOption) (*KeyStrea stream: streamClient, }, nil } + +func NewKvStoreClient(name string) (*KvStoreClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "unable to reach nitric server", + err, + ) + } + + client := v1.NewKvStoreClient(conn) + + return &KvStoreClient{ + name: name, + kvClient: client, + }, nil +} diff --git a/api/keyvalue/store_test.go b/nitric/keyvalue/store_test.go similarity index 97% rename from api/keyvalue/store_test.go rename to nitric/keyvalue/store_test.go index 0a27a94..0ab7e35 100644 --- a/api/keyvalue/store_test.go +++ b/nitric/keyvalue/store_test.go @@ -32,17 +32,17 @@ var _ = Describe("KeyValue Store API", func() { var ( ctrl *gomock.Controller mockKV *mock_v1.MockKvStoreClient - kv *keyValueImpl - store Store + kv *KvStoreClient + store KvStoreClientIface storeName string ) BeforeEach(func() { ctrl = gomock.NewController(GinkgoT()) mockKV = mock_v1.NewMockKvStoreClient(ctrl) - kv = &keyValueImpl{kvClient: mockKV} storeName = "test-store" - store = kv.Store(storeName) + kv = &KvStoreClient{name: storeName, kvClient: mockKV} + store = kv }) AfterEach(func() { diff --git a/nitric/manager.go b/nitric/manager.go index e8dd831..88b2abe 100644 --- a/nitric/manager.go +++ b/nitric/manager.go @@ -25,25 +25,11 @@ import ( multierror "github.com/missionMeteora/toolkit/errors" "google.golang.org/grpc" - apierrors "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/keyvalue" - "github.com/nitrictech/go-sdk/api/queues" - "github.com/nitrictech/go-sdk/api/secrets" - "github.com/nitrictech/go-sdk/api/storage" - "github.com/nitrictech/go-sdk/api/topics" "github.com/nitrictech/go-sdk/constants" + apierrors "github.com/nitrictech/go-sdk/nitric/errors" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) -// Manager is the top level object that resources are created on. -type Manager interface { - Run() error - addWorker(name string, s streamWorker) - resourceServiceClient() (v1.ResourcesClient, error) - registerResource(request *v1.ResourceDeclareRequest) <-chan RegisterResult - registerPolicy(res *v1.ResourceIdentifier, actions ...v1.Action) (*manager, error) -} - type RegisterResult struct { Identifier *v1.ResourceIdentifier Err error @@ -54,12 +40,7 @@ type manager struct { conn grpc.ClientConnInterface connMutex sync.Mutex - rsc v1.ResourcesClient - topics topics.Topics - storage storage.Storage - secrets secrets.Secrets - queues queues.Queues - kvstores keyvalue.KeyValue + rsc v1.ResourcesClient } var defaultManager = New() @@ -67,7 +48,7 @@ var defaultManager = New() // New is used to create the top level resource manager. // Note: this is not required if you are using // resources.NewApi() and the like. These use a default manager instance. -func New() Manager { +func New() *manager { return &manager{ workers: map[string]streamWorker{}, } @@ -127,26 +108,26 @@ func (m *manager) registerResource(request *v1.ResourceDeclareRequest) <-chan Re return registerResourceChan } -func (m *manager) registerPolicy(res *v1.ResourceIdentifier, actions ...v1.Action) (*manager, error) { +func (m *manager) registerPolicy(res *v1.ResourceIdentifier, actions ...v1.Action) error { rsc, err := m.resourceServiceClient() if err != nil { - return m, err + return err } _, err = rsc.Declare(context.Background(), functionResourceDeclareRequest(res, actions)) if err != nil { - return m, err + return err } - return m, nil + return nil } -// Run will run the function and callback the required handlers when these events are received. +// Run will run the service and callback the required handlers when events are received. func Run() error { - return defaultManager.Run() + return defaultManager.run() } -func (m *manager) Run() error { +func (m *manager) run() error { wg := sync.WaitGroup{} errList := &multierror.ErrorList{} @@ -156,7 +137,7 @@ func (m *manager) Run() error { defer wg.Done() if err := s.Start(context.TODO()); err != nil { - if isBuildEnvirnonment() && isEOF(err) { + if isBuildEnvironment() && isEOF(err) { // ignore the EOF error when running code-as-config. return } @@ -171,8 +152,8 @@ func (m *manager) Run() error { return errList.Err() } -// IsBuildEnvirnonment will return true if the code is running during config discovery. -func isBuildEnvirnonment() bool { +// IsBuildEnvironment will return true if the code is running during config discovery. +func isBuildEnvironment() bool { return strings.ToLower(os.Getenv("NITRIC_ENVIRONMENT")) == "build" } diff --git a/nitric/manager_test.go b/nitric/manager_test.go index 7b3cf42..bd946a6 100644 --- a/nitric/manager_test.go +++ b/nitric/manager_test.go @@ -21,7 +21,7 @@ package nitric // . "github.com/onsi/ginkgo" // . "github.com/onsi/gomega" -// apierrors "github.com/nitrictech/go-sdk/api/errors" +// apierrors "github.com/nitrictech/go-sdk/nitric/errors" // ) // var _ = Describe("manager", func() { diff --git a/nitric/oidc.go b/nitric/oidc.go index 8edea02..7073dbb 100644 --- a/nitric/oidc.go +++ b/nitric/oidc.go @@ -45,7 +45,7 @@ type oidcSecurityDefinition struct { Issuer string Audiences []string - manager Manager + manager *manager } func NewOidcSecurityDefinition(apiName string, options OidcOptions) (OidcSecurityDefinition, error) { diff --git a/nitric/options.go b/nitric/options.go index 35b66c3..3a1c50a 100644 --- a/nitric/options.go +++ b/nitric/options.go @@ -15,7 +15,7 @@ package nitric import ( - "github.com/nitrictech/go-sdk/api/apis" + "github.com/nitrictech/go-sdk/nitric/apis" ) type ( @@ -74,7 +74,6 @@ func WithSecurity(oidcOptions OidcOptions) ApiOption { } } -// WithPath - Prefixes API with the given path func WithPath(path string) ApiOption { return func(api *api) { api.path = path diff --git a/nitric/queue.go b/nitric/queue.go index c96ad76..c393d20 100644 --- a/nitric/queue.go +++ b/nitric/queue.go @@ -17,7 +17,7 @@ package nitric import ( "fmt" - "github.com/nitrictech/go-sdk/api/queues" + "github.com/nitrictech/go-sdk/nitric/queues" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) @@ -31,15 +31,17 @@ const ( var QueueEverything []QueuePermission = []QueuePermission{QueueEnqueue, QueueDequeue} type Queue interface { - Allow(QueuePermission, ...QueuePermission) (queues.Queue, error) + // Allow requests the given permissions to the queue. + Allow(QueuePermission, ...QueuePermission) (*queues.QueueClient, error) } type queue struct { name string - manager Manager + manager *manager registerChan <-chan RegisterResult } +// NewQueue - Create a new Queue resource func NewQueue(name string) *queue { queue := &queue{ name: name, @@ -60,8 +62,7 @@ func NewQueue(name string) *queue { return queue } -// NewQueue registers this queue as a required resource for the calling function/container. -func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission) (queues.Queue, error) { +func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission) (*queues.QueueClient, error) { allPerms := append([]QueuePermission{permission}, permissions...) actions := []v1.Action{} @@ -81,17 +82,10 @@ func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission return nil, registerResult.Err } - m, err := q.manager.registerPolicy(registerResult.Identifier, actions...) + err := q.manager.registerPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - if m.queues == nil { - m.queues, err = queues.New() - if err != nil { - return nil, err - } - } - - return m.queues.Queue(q.name), nil + return queues.NewQueueClient(q.name) } diff --git a/nitric/queue_test.go b/nitric/queue_test.go deleted file mode 100644 index 1cb6091..0000000 --- a/nitric/queue_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -// import ( -// "context" - -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" - -// "github.com/golang/mock/gomock" - -// mock_v1 "github.com/nitrictech/go-sdk/mocks" -// "github.com/nitrictech/go-sdk/mocks/mockapi" -// nitricv1 "github.com/nitrictech/nitric/core/pkg/api/nitric/v1" -// ) - -// var _ = Describe("queue", func() { -// ctrl := gomock.NewController(GinkgoT()) -// Context("New", func() { -// mockConn := mock_v1.NewMockClientConnInterface(ctrl) -// When("valid args", func() { -// mockClient := mock_v1.NewMockResourceServiceClient(ctrl) -// mockQueues := mockapi.NewMockQueues(ctrl) - -// m := &manager{ -// workers: map[string]Starter{}, -// conn: mockConn, -// rsc: mockClient, -// queues: mockQueues, -// } - -// mockClient.EXPECT().Declare(context.Background(), -// &nitricv1.ResourceDeclareRequest{ -// Resource: &nitricv1.Resource{ -// Type: nitricv1.ResourceType_Queue, -// Name: "wollies", -// }, -// Config: &nitricv1.ResourceDeclareRequest_Queue{ -// Queue: &nitricv1.QueueResource{}, -// }, -// }) - -// mockClient.EXPECT().Declare(context.Background(), -// &nitricv1.ResourceDeclareRequest{ -// Resource: &nitricv1.Resource{ -// Type: nitricv1.ResourceType_Policy, -// }, -// Config: &nitricv1.ResourceDeclareRequest_Policy{ -// Policy: &nitricv1.PolicyResource{ -// Principals: []*nitricv1.Resource{{ -// Type: nitricv1.ResourceType_Function, -// }}, -// Actions: []nitricv1.Action{ -// nitricv1.Action_QueueReceive, -// nitricv1.Action_QueueDetail, -// nitricv1.Action_QueueList, -// }, -// Resources: []*nitricv1.Resource{{ -// Type: nitricv1.ResourceType_Queue, -// Name: "wollies", -// }}, -// }, -// }, -// }) - -// mockQueue := mockapi.NewMockQueue(ctrl) -// mockQueues.EXPECT().Queue("wollies").Return(mockQueue) -// b, err := m.newQueue("wollies", QueueReceiving) - -// It("should not return an error", func() { -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(b).ShouldNot(BeNil()) -// }) -// }) -// }) -// }) diff --git a/api/queues/task.go b/nitric/queues/message.go similarity index 87% rename from api/queues/task.go rename to nitric/queues/message.go index b6f0657..0fa21e7 100644 --- a/api/queues/task.go +++ b/nitric/queues/message.go @@ -17,8 +17,8 @@ package queues import ( "context" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/queues/v1" "github.com/nitrictech/protoutils" ) @@ -32,22 +32,22 @@ type ReceivedMessage interface { Complete(context.Context) error } -type receivedMessageImpl struct { +type leasedMessage struct { queueName string queueClient v1.QueuesClient leaseId string message map[string]interface{} } -func (r *receivedMessageImpl) Message() map[string]interface{} { +func (r *leasedMessage) Message() map[string]interface{} { return r.message } -func (r *receivedMessageImpl) Queue() string { +func (r *leasedMessage) Queue() string { return r.queueName } -func (r *receivedMessageImpl) Complete(ctx context.Context) error { +func (r *leasedMessage) Complete(ctx context.Context) error { _, err := r.queueClient.Complete(ctx, &v1.QueueCompleteRequest{ QueueName: r.queueName, LeaseId: r.leaseId, diff --git a/api/queues/task_test.go b/nitric/queues/message_test.go similarity index 98% rename from api/queues/task_test.go rename to nitric/queues/message_test.go index 798c652..5190feb 100644 --- a/api/queues/task_test.go +++ b/nitric/queues/message_test.go @@ -45,7 +45,7 @@ var _ = Describe("ReceivedMessage", func() { message = map[string]interface{}{ "message": "hello", } - receivedMsg = &receivedMessageImpl{ + receivedMsg = &leasedMessage{ queueName: queueName, queueClient: mockQ, leaseId: leaseID, diff --git a/api/queues/queue.go b/nitric/queues/queue.go similarity index 72% rename from api/queues/queue.go rename to nitric/queues/queue.go index 93629bb..90d67ee 100644 --- a/api/queues/queue.go +++ b/nitric/queues/queue.go @@ -17,13 +17,15 @@ package queues import ( "context" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/queues/v1" + "google.golang.org/grpc" ) -// Queue is a resource for async enqueueing/dequeueing of messages. -type Queue interface { +// QueueClientIface is a resource for async enqueueing/dequeueing of messages. +type QueueClientIface interface { // Name - The name of the queue Name() string // Enqueue - Push a number of messages to a queue @@ -32,16 +34,16 @@ type Queue interface { Dequeue(context.Context, int) ([]ReceivedMessage, error) } -type queueImpl struct { +type QueueClient struct { name string queueClient v1.QueuesClient } -func (q *queueImpl) Name() string { +func (q *QueueClient) Name() string { return q.name } -func (q *queueImpl) Dequeue(ctx context.Context, depth int) ([]ReceivedMessage, error) { +func (q *QueueClient) Dequeue(ctx context.Context, depth int) ([]ReceivedMessage, error) { if depth < 1 { return nil, errors.New(codes.InvalidArgument, "Queue.Dequeue: depth cannot be less than 1") } @@ -57,7 +59,7 @@ func (q *queueImpl) Dequeue(ctx context.Context, depth int) ([]ReceivedMessage, rts := make([]ReceivedMessage, len(r.GetMessages())) for i, message := range r.GetMessages() { - rts[i] = &receivedMessageImpl{ + rts[i] = &leasedMessage{ queueName: q.name, queueClient: q.queueClient, leaseId: message.GetLeaseId(), @@ -68,7 +70,7 @@ func (q *queueImpl) Dequeue(ctx context.Context, depth int) ([]ReceivedMessage, return rts, nil } -func (q *queueImpl) Enqueue(ctx context.Context, messages []map[string]interface{}) ([]*FailedMessage, error) { +func (q *QueueClient) Enqueue(ctx context.Context, messages []map[string]interface{}) ([]*FailedMessage, error) { // Convert SDK Message objects to gRPC Message objects wireMessages := make([]*v1.QueueMessage, len(messages)) for i, message := range messages { @@ -103,3 +105,21 @@ func (q *queueImpl) Enqueue(ctx context.Context, messages []map[string]interface return failedMessages, nil } + +func NewQueueClient(name string) (*QueueClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "unable to reach nitric server", + err, + ) + } + + queueClient := v1.NewQueuesClient(conn) + + return &QueueClient{ + name: name, + queueClient: queueClient, + }, nil +} diff --git a/api/queues/queue_test.go b/nitric/queues/queue_test.go similarity index 96% rename from api/queues/queue_test.go rename to nitric/queues/queue_test.go index fb2252b..a3e35b5 100644 --- a/api/queues/queue_test.go +++ b/nitric/queues/queue_test.go @@ -32,20 +32,19 @@ var _ = Describe("Queue interface", func() { var ( ctrl *gomock.Controller mockQ *mock_v1.MockQueuesClient - queues *queuesImpl queueName string - q Queue + q QueueClientIface ctx context.Context ) BeforeEach(func() { ctrl = gomock.NewController(GinkgoT()) mockQ = mock_v1.NewMockQueuesClient(ctrl) - queues = &queuesImpl{ + queueName = "test-queue" + q = &QueueClient{ queueClient: mockQ, + name: queueName, } - queueName = "test-queue" - q = queues.Queue(queueName) ctx = context.Background() }) @@ -123,7 +122,7 @@ var _ = Describe("Queue interface", func() { var errorMsg string BeforeEach(func() { - errorMsg = "internal errror" + errorMsg = "internal error" mockQ.EXPECT().Enqueue(gomock.Any(), gomock.Any()).Return( nil, errors.New(errorMsg), @@ -192,7 +191,7 @@ var _ = Describe("Queue interface", func() { messages, err := q.Dequeue(ctx, depth) Expect(err).ToNot(HaveOccurred()) - _, ok := messages[0].(*receivedMessageImpl) + _, ok := messages[0].(*leasedMessage) Expect(ok).To(BeTrue()) }) diff --git a/api/queues/queues_suite_test.go b/nitric/queues/queues_suite_test.go similarity index 100% rename from api/queues/queues_suite_test.go rename to nitric/queues/queues_suite_test.go diff --git a/nitric/schedule.go b/nitric/schedule.go index d6bad6c..b3a2669 100644 --- a/nitric/schedule.go +++ b/nitric/schedule.go @@ -17,7 +17,7 @@ package nitric import ( "strings" - "github.com/nitrictech/go-sdk/api/schedules" + "github.com/nitrictech/go-sdk/nitric/schedules" schedulespb "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) @@ -57,12 +57,12 @@ type Schedule interface { type schedule struct { name string - manager Manager + manager *manager } var _ Schedule = (*schedule)(nil) -// NewSchedule provides a new schedule, which can be configured with a rate/cron and a callback to run on the schedule. +// NewSchedule - Create a new Schedule resource func NewSchedule(name string) Schedule { return &schedule{ name: name, diff --git a/nitric/schedule_test.go b/nitric/schedule_test.go deleted file mode 100644 index f408283..0000000 --- a/nitric/schedule_test.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -// import ( -// "github.com/nitrictech/go-sdk/faas" -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" -// ) - -// var _ = Describe("schedule", func() { -// Context("New", func() { -// m := &manager{ -// workers: map[string]Starter{}, -// builders: map[string]faas.HandlerBuilder{}, -// } -// When("valid args", func() { -// err := m.newSchedule("regular").Every("4 minutes", func(ec *faas.EventContext, eh faas.EventHandler) (*faas.EventContext, error) { -// return eh(ec) -// }) - -// It("should not return an error", func() { -// Expect(err).ShouldNot(HaveOccurred()) -// b := m.builders["regular"] -// Expect(b).ToNot(BeNil()) -// }) -// }) -// When("invalid schedule", func() { -// err := m.newSchedule("invalid").Every("four minutes", func(ec *faas.EventContext, eh faas.EventHandler) (*faas.EventContext, error) { -// return eh(ec) -// }) - -// It("should return an error", func() { -// Expect(err).To(MatchError("invalid rate expression four minutes; strconv.Atoi: parsing \"four\": invalid syntax")) -// b := m.builders["invalid"] -// Expect(b).To(BeNil()) -// }) -// }) -// }) -// Context("rateSplit", func() { -// When("hours", func() { -// It("2 hours", func() { -// r, f, err := rateSplit("2 hours") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(2)) -// Expect(f).To(Equal(faas.Frequency("hours"))) -// }) -// It("1 hours", func() { -// r, f, err := rateSplit("1 hours") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(1)) -// Expect(f).To(Equal(faas.Frequency("hours"))) -// }) -// It("hour", func() { -// r, f, err := rateSplit("hour") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(1)) -// Expect(f).To(Equal(faas.Frequency("hours"))) -// }) -// }) -// When("days", func() { -// It("day", func() { -// r, f, err := rateSplit("day") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(1)) -// Expect(f).To(Equal(faas.Frequency("days"))) -// }) -// It("1 day", func() { -// r, f, err := rateSplit("1 days") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(1)) -// Expect(f).To(Equal(faas.Frequency("days"))) -// }) -// It("89 day", func() { -// r, f, err := rateSplit("89 days") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(89)) -// Expect(f).To(Equal(faas.Frequency("days"))) -// }) -// }) -// When("minutes", func() { -// It("minute", func() { -// r, f, err := rateSplit("minute") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(1)) -// Expect(f).To(Equal(faas.Frequency("minutes"))) -// }) -// It("1 minutes", func() { -// r, f, err := rateSplit("1 minutes") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(1)) -// Expect(f).To(Equal(faas.Frequency("minutes"))) -// }) -// It("89 minutes", func() { -// r, f, err := rateSplit("89 minutes") -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(r).To(Equal(89)) -// Expect(f).To(Equal(faas.Frequency("minutes"))) -// }) -// }) -// }) -// }) diff --git a/nitric/schedule_workers.go b/nitric/schedule_workers.go index 9ff12d5..e2104ff 100644 --- a/nitric/schedule_workers.go +++ b/nitric/schedule_workers.go @@ -21,10 +21,10 @@ import ( "google.golang.org/grpc" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/api/schedules" "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + "github.com/nitrictech/go-sdk/nitric/schedules" v1 "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) diff --git a/api/schedules/context.go b/nitric/schedules/context.go similarity index 97% rename from api/schedules/context.go rename to nitric/schedules/context.go index d215937..ae131a5 100644 --- a/api/schedules/context.go +++ b/nitric/schedules/context.go @@ -35,7 +35,7 @@ func (c *Ctx) ToClientMessage() *schedulespb.ClientMessage { func NewCtx(msg *schedulespb.ServerMessage) *Ctx { return &Ctx{ id: msg.Id, - Request: &requestImpl{ + Request: &scheduleRequest{ scheduleName: msg.GetIntervalRequest().ScheduleName, }, Response: &Response{ diff --git a/api/schedules/request.go b/nitric/schedules/request.go similarity index 90% rename from api/schedules/request.go rename to nitric/schedules/request.go index 1c2bb42..3a75d65 100644 --- a/api/schedules/request.go +++ b/nitric/schedules/request.go @@ -18,10 +18,10 @@ type Request interface { ScheduleName() string } -type requestImpl struct { +type scheduleRequest struct { scheduleName string } -func (i *requestImpl) ScheduleName() string { +func (i *scheduleRequest) ScheduleName() string { return i.scheduleName } diff --git a/api/schedules/response.go b/nitric/schedules/response.go similarity index 100% rename from api/schedules/response.go rename to nitric/schedules/response.go diff --git a/nitric/secret.go b/nitric/secret.go index a1c80c5..c041779 100644 --- a/nitric/secret.go +++ b/nitric/secret.go @@ -17,7 +17,7 @@ package nitric import ( "fmt" - "github.com/nitrictech/go-sdk/api/secrets" + "github.com/nitrictech/go-sdk/nitric/secrets" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) @@ -31,15 +31,17 @@ const ( var SecretEverything []SecretPermission = []SecretPermission{SecretAccess, SecretPut} type Secret interface { - Allow(SecretPermission, ...SecretPermission) (secrets.SecretRef, error) + // Allow requests the given permissions to the secret. + Allow(SecretPermission, ...SecretPermission) (*secrets.SecretClient, error) } type secret struct { name string - manager Manager + manager *manager registerChan <-chan RegisterResult } +// NewSecret - Create a new Secret resource func NewSecret(name string) *secret { secret := &secret{ name: name, @@ -59,7 +61,7 @@ func NewSecret(name string) *secret { return secret } -func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermission) (secrets.SecretRef, error) { +func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermission) (*secrets.SecretClient, error) { allPerms := append([]SecretPermission{permission}, permissions...) actions := []v1.Action{} @@ -79,17 +81,10 @@ func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermiss return nil, registerResult.Err } - m, err := s.manager.registerPolicy(registerResult.Identifier, actions...) + err := s.manager.registerPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - if m.secrets == nil { - m.secrets, err = secrets.New() - if err != nil { - return nil, err - } - } - - return m.secrets.Secret(s.name), nil + return secrets.NewSecretClient(s.name) } diff --git a/nitric/secret_test.go b/nitric/secret_test.go deleted file mode 100644 index cb75caf..0000000 --- a/nitric/secret_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -// import ( -// "context" - -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" - -// "github.com/golang/mock/gomock" - -// mock_v1 "github.com/nitrictech/go-sdk/mocks" -// "github.com/nitrictech/go-sdk/mocks/mockapi" -// nitricv1 "github.com/nitrictech/nitric/core/pkg/api/nitric/v1" -// ) - -// var _ = Describe("secrets", func() { -// ctrl := gomock.NewController(GinkgoT()) -// Context("New", func() { -// mockConn := mock_v1.NewMockClientConnInterface(ctrl) -// When("valid args", func() { -// mockClient := mock_v1.NewMockResourceServiceClient(ctrl) -// mockSecrets := mockapi.NewMockSecrets(ctrl) - -// m := &manager{ -// workers: map[string]Starter{}, -// conn: mockConn, -// rsc: mockClient, -// secrets: mockSecrets, -// } - -// mockClient.EXPECT().Declare(context.Background(), -// &nitricv1.ResourceDeclareRequest{ -// Resource: &nitricv1.Resource{ -// Type: nitricv1.ResourceType_Secret, -// Name: "gold", -// }, -// Config: &nitricv1.ResourceDeclareRequest_Secret{ -// Secret: &nitricv1.SecretResource{}, -// }, -// }) - -// mockClient.EXPECT().Declare(context.Background(), -// &nitricv1.ResourceDeclareRequest{ -// Resource: &nitricv1.Resource{ -// Type: nitricv1.ResourceType_Policy, -// }, -// Config: &nitricv1.ResourceDeclareRequest_Policy{ -// Policy: &nitricv1.PolicyResource{ -// Principals: []*nitricv1.Resource{{ -// Type: nitricv1.ResourceType_Function, -// }}, -// Actions: []nitricv1.Action{ -// nitricv1.Action_SecretPut, nitricv1.Action_SecretAccess, -// }, -// Resources: []*nitricv1.Resource{{ -// Type: nitricv1.ResourceType_Secret, -// Name: "gold", -// }}, -// }, -// }, -// }) - -// mockSecretRef := mockapi.NewMockSecretRef(ctrl) -// mockSecrets.EXPECT().Secret("gold").Return(mockSecretRef) -// b, err := m.newSecret("gold", SecretPutting, SecretAccessing) - -// It("should not return an error", func() { -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(b).ShouldNot(BeNil()) -// }) -// }) -// }) -// }) diff --git a/nitric/secrets/secrets.go b/nitric/secrets/secrets.go new file mode 100644 index 0000000..04854bb --- /dev/null +++ b/nitric/secrets/secrets.go @@ -0,0 +1,112 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 secrets + +import ( + "context" + + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" + "google.golang.org/grpc" +) + +type SecretValue []byte + +func (s SecretValue) AsString() string { + return string(s) +} + +type SecretClientIface interface { + // Name - Return the name of this secret + Name() string + // Put - Store a new value in this secret, returning a reference to the new version created + Put(context.Context, []byte) (string, error) + // Access - Access the latest version of this secret + Access(context.Context) (SecretValue, error) + // AccessVersion - Access a specific version of the secret + AccessVersion(context.Context, string) (SecretValue, error) +} + +var _ SecretClientIface = (*SecretClient)(nil) + +// SecretClient - Reference to a cloud secret +type SecretClient struct { + name string + secretClient v1.SecretManagerClient +} + +// Name - Return the name of this secret +func (s *SecretClient) Name() string { + return s.name +} + +// Put - Store a new value in this secret, returning a reference to the new version created +func (s *SecretClient) Put(ctx context.Context, sec []byte) (string, error) { + resp, err := s.secretClient.Put(ctx, &v1.SecretPutRequest{ + Secret: &v1.Secret{ + Name: s.name, + }, + Value: sec, + }) + if err != nil { + return "", errors.FromGrpcError(err) + } + + return resp.GetSecretVersion().Version, nil +} + +const latestVersionId = "latest" + +// Access - Access the latest version of this secret +func (s *SecretClient) Access(ctx context.Context) (SecretValue, error) { + return s.AccessVersion(ctx, latestVersionId) +} + +// AccessVersion - Access a specific version of the secret +func (s *SecretClient) AccessVersion(ctx context.Context, version string) (SecretValue, error) { + r, err := s.secretClient.Access(ctx, &v1.SecretAccessRequest{ + SecretVersion: &v1.SecretVersion{ + Secret: &v1.Secret{ + Name: s.name, + }, + Version: version, + }, + }) + if err != nil { + return nil, errors.FromGrpcError(err) + } + + return SecretValue(r.GetValue()), nil +} + +func NewSecretClient(name string) (*SecretClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "unable to reach nitric server", + err, + ) + } + + sClient := v1.NewSecretManagerClient(conn) + + return &SecretClient{ + secretClient: sClient, + name: name, + }, nil +} diff --git a/api/secrets/secrets_suite_test.go b/nitric/secrets/secrets_suite_test.go similarity index 100% rename from api/secrets/secrets_suite_test.go rename to nitric/secrets/secrets_suite_test.go diff --git a/api/secrets/secret_ref_test.go b/nitric/secrets/secrets_test.go similarity index 55% rename from api/secrets/secret_ref_test.go rename to nitric/secrets/secrets_test.go index 24c4373..171d4c6 100644 --- a/api/secrets/secret_ref_test.go +++ b/nitric/secrets/secrets_test.go @@ -29,22 +29,19 @@ import ( var _ = Describe("secretRefImpl", func() { var ( - ctrl *gomock.Controller - mockSC *mock_v1.MockSecretManagerClient - secrets *secretsImpl - secretsName string - sr SecretRef - ctx context.Context + ctrl *gomock.Controller + mockSC *mock_v1.MockSecretManagerClient + secret *SecretClient + ctx context.Context ) BeforeEach(func() { ctrl = gomock.NewController(GinkgoT()) mockSC = mock_v1.NewMockSecretManagerClient(ctrl) - secrets = &secretsImpl{ + secret = &SecretClient{ + name: "test-secret", secretClient: mockSC, } - secretsName = "test-secrets" - sr = secrets.Secret(secretsName) ctx = context.Background() }) @@ -55,72 +52,19 @@ var _ = Describe("secretRefImpl", func() { Context("Having a valid secretRef", func() { Describe("Name", func() { It("should return the correct secrets name", func() { - Expect(sr.Name()).To(Equal(secretsName)) - }) - }) - - Describe("Version", func() { - versionName := "test-version" - _sr := &secretRefImpl{ - name: secretsName, - secretClient: mockSC, - } - sv := _sr.Version(versionName) - svi, ok := sv.(*secretVersionRefImpl) - - It("should be of type secretVersionRefImpl", func() { - Expect(ok).To(BeTrue()) - }) - - It("should share a secret client references with its parent secret", func() { - Expect(svi.secretClient).To(Equal(_sr.secretClient)) - }) - - It("should have a back reference to it's parent secret", func() { - Expect(svi.secret).To(Equal(_sr)) - }) - - It("should have a the requested version name", func() { - Expect(svi.version).To(Equal(versionName)) - }) - }) - - Describe("Latest", func() { - When("retrieving a the latest secret version reference", func() { - _sr := &secretRefImpl{ - name: secretsName, - secretClient: mockSC, - } - sv := _sr.Latest() - svi, ok := sv.(*secretVersionRefImpl) - - It("should be of type secretVersionRefImpl", func() { - Expect(ok).To(BeTrue()) - }) - - It("should share a secret client references with its parent secret", func() { - Expect(svi.secretClient).To(Equal(_sr.secretClient)) - }) - - It("should have a back reference to it's parent secret", func() { - Expect(svi.secret).To(Equal(_sr)) - }) - - It("should have 'latest' as it's version name", func() { - Expect(svi.version).To(Equal("latest")) - }) + Expect(secret.Name()).To(Equal("test-secret")) }) }) Describe("Put", func() { var ( - _sr *secretRefImpl + _sr *SecretClient secretValue []byte ) BeforeEach(func() { - _sr = &secretRefImpl{ - name: secretsName, + _sr = &SecretClient{ + name: "test-secret", secretClient: mockSC, } secretValue = []byte("ssssshhhh... it's a secret") @@ -158,16 +102,8 @@ var _ = Describe("secretRefImpl", func() { By("not returning an error") Expect(err).ToNot(HaveOccurred()) - svi, ok := sv.(*secretVersionRefImpl) - - By("returning a secretVersionRefImpl") - Expect(ok).To(BeTrue()) - - By("returning the correct secret version") - Expect(svi.version).To(Equal(versionName)) - - By("attaching a reference to the parent secret") - Expect(svi.secret).To(Equal(_sr)) + By("returning a string secret version") + Expect(sv).To(Equal(versionName)) }) }) @@ -190,8 +126,8 @@ var _ = Describe("secretRefImpl", func() { Expect(err).To(HaveOccurred()) Expect(strings.Contains(err.Error(), errorMsg)).To(BeTrue()) - By("returning a nil secret version reference") - Expect(sv).To(BeNil()) + By("returning a blank secret version reference") + Expect(sv).To(BeEmpty()) }) }) }) diff --git a/nitric/storage/bucket.go b/nitric/storage/bucket.go new file mode 100644 index 0000000..d4456cf --- /dev/null +++ b/nitric/storage/bucket.go @@ -0,0 +1,191 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 storage + +import ( + "context" + "time" + + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/durationpb" +) + +// Cloud storage bucket resource for large file storage. +type BucketIface interface { + // Name - Get the name of the bucket + Name() string + // ListFiles - List the files in the bucket + ListFiles(ctx context.Context) ([]string, error) + // Read - Read this object + Read(ctx context.Context, key string) ([]byte, error) + // Write - Write this object + Write(ctx context.Context, key string, data []byte) error + // Delete - Delete this object + Delete(ctx context.Context, key string) error + // UploadUrl - Creates a signed Url for uploading this file reference + UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) + // DownloadUrl - Creates a signed Url for downloading this file reference + DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) +} + +var _ BucketIface = (*Bucket)(nil) + +type Bucket struct { + storageClient v1.StorageClient + name string +} + +func (o *Bucket) Read(ctx context.Context, key string) ([]byte, error) { + r, err := o.storageClient.Read(ctx, &v1.StorageReadRequest{ + BucketName: o.name, + Key: key, + }) + if err != nil { + return nil, errors.FromGrpcError(err) + } + + return r.GetBody(), nil +} + +func (o *Bucket) Write(ctx context.Context, key string, content []byte) error { + if _, err := o.storageClient.Write(ctx, &v1.StorageWriteRequest{ + BucketName: o.name, + Key: key, + Body: content, + }); err != nil { + return errors.FromGrpcError(err) + } + + return nil +} + +func (o *Bucket) Delete(ctx context.Context, key string) error { + if _, err := o.storageClient.Delete(ctx, &v1.StorageDeleteRequest{ + BucketName: o.name, + Key: key, + }); err != nil { + return errors.FromGrpcError(err) + } + + return nil +} + +func (b *Bucket) ListFiles(ctx context.Context) ([]string, error) { + resp, err := b.storageClient.ListBlobs(ctx, &v1.StorageListBlobsRequest{ + BucketName: b.name, + }) + if err != nil { + return nil, err + } + + fileRefs := make([]string, 0) + + for _, f := range resp.Blobs { + fileRefs = append(fileRefs, f.Key) + } + + return fileRefs, nil +} + +type Mode int + +const ( + ModeRead Mode = iota + ModeWrite +) + +type presignUrlOptions struct { + mode Mode + expiry time.Duration +} + +type PresignUrlOption func(opts *presignUrlOptions) + +func WithPresignUrlExpiry(expiry time.Duration) PresignUrlOption { + return func(opts *presignUrlOptions) { + opts.expiry = expiry + } +} + +func getPresignUrlOpts(mode Mode, opts ...PresignUrlOption) *presignUrlOptions { + defaultOpts := &presignUrlOptions{ + mode: mode, + expiry: time.Duration(time.Minute * 5), + } + + for _, opt := range opts { + opt(defaultOpts) + } + + return defaultOpts +} + +func (o *Bucket) UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { + optsWithDefaults := getPresignUrlOpts(ModeWrite, opts...) + + return o.signUrl(ctx, key, optsWithDefaults) +} + +func (o *Bucket) DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { + optsWithDefaults := getPresignUrlOpts(ModeRead, opts...) + + return o.signUrl(ctx, key, optsWithDefaults) +} + +func (o *Bucket) signUrl(ctx context.Context, key string, opts *presignUrlOptions) (string, error) { + op := v1.StoragePreSignUrlRequest_READ + + if opts.mode == ModeWrite { + op = v1.StoragePreSignUrlRequest_WRITE + } + + r, err := o.storageClient.PreSignUrl(ctx, &v1.StoragePreSignUrlRequest{ + BucketName: o.name, + Key: key, + Operation: op, + Expiry: durationpb.New(opts.expiry), + }) + if err != nil { + return "", errors.FromGrpcError(err) + } + + return r.Url, nil +} + +func (b *Bucket) Name() string { + return b.name +} + +func NewBucket(name string) (*Bucket, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "unable to reach nitric server", + err, + ) + } + + storageClient := v1.NewStorageClient(conn) + + return &Bucket{ + name: name, + storageClient: storageClient, + }, nil +} diff --git a/api/storage/bucket_test.go b/nitric/storage/bucket_test.go similarity index 70% rename from api/storage/bucket_test.go rename to nitric/storage/bucket_test.go index ee0f6b4..4ac641b 100644 --- a/api/storage/bucket_test.go +++ b/nitric/storage/bucket_test.go @@ -31,9 +31,8 @@ var _ = Describe("Bucket", func() { var ( ctrl *gomock.Controller mockStorage *mock_v1.MockStorageClient - bucket *bucketImpl + bucket *Bucket bucketName string - fileName string ctx context.Context ) @@ -42,9 +41,8 @@ var _ = Describe("Bucket", func() { mockStorage = mock_v1.NewMockStorageClient(ctrl) bucketName = "test-bucket" - fileName = "test-file.txt" - bucket = &bucketImpl{ + bucket = &Bucket{ name: bucketName, storageClient: mockStorage, } @@ -56,37 +54,8 @@ var _ = Describe("Bucket", func() { ctrl.Finish() }) - Describe("File()", func() { - When("creating a new File reference", func() { - var ( - file File - fileI *fileImpl - ok bool - ) - - BeforeEach(func() { - file = bucket.File(fileName) - fileI, ok = file.(*fileImpl) - }) - - It("it should successfully return File Instance", func() { - By("returning an fileImpl instance") - Expect(ok).To(BeTrue()) - - By("having the provided file name") - Expect(fileI.key).To(Equal(fileName)) - - By("sharing the bucket name") - Expect(fileI.bucket).To(Equal(bucketName)) - - By("sharing the Bucket's gRPC client") - Expect(fileI.storageClient).To(Equal(mockStorage)) - }) - }) - }) - - Describe("Files()", func() { - When("the gRPC opreation of ListBlobs fails", func() { + Describe("ListFiles()", func() { + When("the gRPC operation of ListBlobs fails", func() { var errorMsg string BeforeEach(func() { @@ -100,7 +69,7 @@ var _ = Describe("Bucket", func() { It("should return an error", func() { By("calling Files() on the bucket reference") - files, err := bucket.Files(ctx) + files, err := bucket.ListFiles(ctx) By("receiving an error with same error message") Expect(err).Should(HaveOccurred()) @@ -111,21 +80,19 @@ var _ = Describe("Bucket", func() { }) }) - When("the gRPC opreation of ListBlobs succeeds", func() { - var files []File + When("the gRPC operation of ListBlobs succeeds", func() { + var files []string BeforeEach(func() { - files = []File{ - bucket.File("file-1.txt"), - bucket.File("file-2.txt"), + files = []string{ + "file-1.txt", + "file-2.txt", } blobs := make([]*v1.Blob, 0, len(files)) for _, file := range files { - fileI, ok := file.(*fileImpl) - Expect(ok).To(BeTrue()) blobs = append(blobs, &v1.Blob{ - Key: fileI.key, + Key: file, }) } @@ -139,7 +106,7 @@ var _ = Describe("Bucket", func() { It("should list the files in the bucket", func() { By("bucket.Files() being called") - _files, err := bucket.Files(ctx) + _files, err := bucket.ListFiles(ctx) By("not returning an error") Expect(err).ToNot(HaveOccurred()) diff --git a/api/storage/context.go b/nitric/storage/context.go similarity index 100% rename from api/storage/context.go rename to nitric/storage/context.go diff --git a/api/storage/request.go b/nitric/storage/request.go similarity index 100% rename from api/storage/request.go rename to nitric/storage/request.go diff --git a/api/storage/response.go b/nitric/storage/response.go similarity index 100% rename from api/storage/response.go rename to nitric/storage/response.go diff --git a/api/storage/storage_suite_test.go b/nitric/storage/storage_suite_test.go similarity index 100% rename from api/storage/storage_suite_test.go rename to nitric/storage/storage_suite_test.go diff --git a/nitric/topic.go b/nitric/topic.go index 5dfad31..da23fdc 100644 --- a/nitric/topic.go +++ b/nitric/topic.go @@ -17,7 +17,7 @@ package nitric import ( "fmt" - "github.com/nitrictech/go-sdk/api/topics" + "github.com/nitrictech/go-sdk/nitric/topics" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" @@ -27,16 +27,13 @@ import ( type TopicPermission string const ( - // TopicPublishing is required to call Publish on a topic. + // TopicPublish is required to call Publish on a topic. TopicPublish TopicPermission = "publish" ) -type Topic interface { - topics.Topic -} - type SubscribableTopic interface { - Allow(TopicPermission, ...TopicPermission) (Topic, error) + // Allow requests the given permissions to the topic. + Allow(TopicPermission, ...TopicPermission) (*topics.TopicClient, error) // Subscribe will register and start a subscription handler that will be called for all events from this topic. // Valid function signatures for middleware are: @@ -56,14 +53,14 @@ type SubscribableTopic interface { } type topic struct { - topics.Topic + topics.TopicClientIface - manager Manager + manager *manager } type subscribableTopic struct { name string - manager Manager + manager *manager registerChan <-chan RegisterResult } @@ -87,7 +84,7 @@ func NewTopic(name string) SubscribableTopic { return topic } -func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...TopicPermission) (Topic, error) { +func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...TopicPermission) (*topics.TopicClient, error) { allPerms := append([]TopicPermission{permission}, permissions...) actions := []v1.Action{} @@ -105,23 +102,12 @@ func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...Top return nil, registerResult.Err } - m, err := t.manager.registerPolicy(registerResult.Identifier, actions...) + err := t.manager.registerPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - if m.topics == nil { - evts, err := topics.New() - if err != nil { - return nil, err - } - m.topics = evts - } - - return &topic{ - Topic: m.topics.Topic(t.name), - manager: m, - }, nil + return topics.NewTopicClient(t.name) } func (t *subscribableTopic) Subscribe(middleware ...interface{}) { diff --git a/nitric/topic_test.go b/nitric/topic_test.go deleted file mode 100644 index 25644a8..0000000 --- a/nitric/topic_test.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -// import ( -// "context" - -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" - -// "github.com/golang/mock/gomock" - -// mock_v1 "github.com/nitrictech/go-sdk/mocks" -// "github.com/nitrictech/go-sdk/mocks/mockapi" -// nitricv1 "github.com/nitrictech/nitric/core/pkg/api/nitric/v1" -// ) - -// var _ = Describe("topics", func() { -// ctrl := gomock.NewController(GinkgoT()) -// Context("New", func() { -// mockConn := mock_v1.NewMockClientConnInterface(ctrl) -// When("valid args", func() { -// mockClient := mock_v1.NewMockResourceServiceClient(ctrl) -// mockEvents := mockapi.NewMockEvents(ctrl) - -// m := &manager{ -// workers: map[string]Starter{}, -// conn: mockConn, -// rsc: mockClient, -// evts: mockEvents, -// } - -// mockClient.EXPECT().Declare(context.Background(), -// &nitricv1.ResourceDeclareRequest{ -// Resource: &nitricv1.Resource{ -// Type: nitricv1.ResourceType_Topic, -// Name: "news", -// }, -// Config: &nitricv1.ResourceDeclareRequest_Topic{ -// Topic: &nitricv1.TopicResource{}, -// }, -// }) - -// mockClient.EXPECT().Declare(context.Background(), -// &nitricv1.ResourceDeclareRequest{ -// Resource: &nitricv1.Resource{ -// Type: nitricv1.ResourceType_Policy, -// }, -// Config: &nitricv1.ResourceDeclareRequest_Policy{ -// Policy: &nitricv1.PolicyResource{ -// Principals: []*nitricv1.Resource{{ -// Type: nitricv1.ResourceType_Function, -// }}, -// Actions: []nitricv1.Action{}, -// Resources: []*nitricv1.Resource{{ -// Type: nitricv1.ResourceType_Topic, -// Name: "news", -// }}, -// }, -// }, -// }) - -// mockTopic := mockapi.NewMockTopic(ctrl) -// mockEvents.EXPECT().Topic("news").Return(mockTopic) -// b, err := m.newTopic("news") - -// It("should not return an error", func() { -// Expect(err).ShouldNot(HaveOccurred()) -// Expect(b).ShouldNot(BeNil()) -// }) -// }) -// }) -// }) diff --git a/nitric/topic_workers.go b/nitric/topic_workers.go index cb37d86..fa071af 100644 --- a/nitric/topic_workers.go +++ b/nitric/topic_workers.go @@ -22,10 +22,10 @@ import ( errorsstd "errors" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/api/topics" "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + "github.com/nitrictech/go-sdk/nitric/topics" v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" ) diff --git a/api/topics/context.go b/nitric/topics/context.go similarity index 100% rename from api/topics/context.go rename to nitric/topics/context.go diff --git a/api/topics/request.go b/nitric/topics/request.go similarity index 100% rename from api/topics/request.go rename to nitric/topics/request.go diff --git a/api/topics/response.go b/nitric/topics/response.go similarity index 100% rename from api/topics/response.go rename to nitric/topics/response.go diff --git a/api/topics/topic.go b/nitric/topics/topic.go similarity index 67% rename from api/topics/topic.go rename to nitric/topics/topic.go index 78257ff..d2ca33d 100644 --- a/api/topics/topic.go +++ b/nitric/topics/topic.go @@ -18,18 +18,20 @@ import ( "context" "time" + "google.golang.org/grpc" "google.golang.org/protobuf/types/known/durationpb" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" "github.com/nitrictech/protoutils" ) type PublishOption = func(*v1.TopicPublishRequest) -// Topic for pub/sub async messaging. -type Topic interface { +// TopicClientIface for pub/sub async messaging. +type TopicClientIface interface { // Name returns the Topic name. Name() string @@ -37,12 +39,12 @@ type Topic interface { Publish(context.Context, map[string]interface{}, ...PublishOption) error } -type topicImpl struct { +type TopicClient struct { name string topicClient v1.TopicsClient } -func (s *topicImpl) Name() string { +func (s *TopicClient) Name() string { return s.name } @@ -53,7 +55,7 @@ func WithDelay(duration time.Duration) func(*v1.TopicPublishRequest) { } } -func (s *topicImpl) Publish(ctx context.Context, message map[string]interface{}, opts ...PublishOption) error { +func (s *TopicClient) Publish(ctx context.Context, message map[string]interface{}, opts ...PublishOption) error { // Convert payload to Protobuf Struct payloadStruct, err := protoutils.NewStruct(message) if err != nil { @@ -81,3 +83,24 @@ func (s *topicImpl) Publish(ctx context.Context, message map[string]interface{}, return nil } + +func NewTopicClient(name string) (*TopicClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "topic.NewTopic: Unable to reach Nitric server", + err, + ) + } + + topicClient := v1.NewTopicsClient(conn) + if err != nil { + return nil, errors.NewWithCause(codes.Internal, "NewTopic", err) + } + + return &TopicClient{ + name: name, + topicClient: topicClient, + }, nil +} diff --git a/api/topics/topic_test.go b/nitric/topics/topic_test.go similarity index 98% rename from api/topics/topic_test.go rename to nitric/topics/topic_test.go index e02a0d4..398fee7 100644 --- a/api/topics/topic_test.go +++ b/nitric/topics/topic_test.go @@ -32,7 +32,7 @@ var _ = Describe("File", func() { var ( ctrl *gomock.Controller mockTopic *mock_v1.MockTopicsClient - t Topic + t *TopicClient topicName string ctx context.Context ) @@ -42,7 +42,7 @@ var _ = Describe("File", func() { mockTopic = mock_v1.NewMockTopicsClient(ctrl) topicName = "test-topic" - t = &topicImpl{ + t = &TopicClient{ name: topicName, topicClient: mockTopic, } diff --git a/api/topics/topics_suite_test.go b/nitric/topics/topics_suite_test.go similarity index 100% rename from api/topics/topics_suite_test.go rename to nitric/topics/topics_suite_test.go diff --git a/nitric/websocket.go b/nitric/websocket.go index 57f3db7..9e2b90d 100644 --- a/nitric/websocket.go +++ b/nitric/websocket.go @@ -18,15 +18,33 @@ import ( "context" "strings" - "github.com/nitrictech/go-sdk/api/websockets" + "github.com/nitrictech/go-sdk/nitric/websockets" resourcesv1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" websocketsv1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) +// Websocket - Nitric Websocket API Resource type Websocket interface { + // Name - Get the name of the Websocket API Name() string + // On registers a handler for a specific event type on the websocket + // Valid function signatures for middleware are: + // + // func() + // func() error + // func(*websocket.Ctx) + // func(*websocket.Ctx) error + // func(*websocket.Ctx) *websocket.Ctx + // func(*websocket.Ctx) (*websocket.Ctx, error) + // func(*websocket.Ctx, Handler[websocket.Ctx]) *websocket.Ctx + // func(*websocket.Ctx, Handler[websocket.Ctx]) error + // func(*websocket.Ctx, Handler[websocket.Ctx]) (*websocket.Ctx, error) + // Middleware[websocket.Ctx] + // Handler[websocket.Ctx] On(eventType websockets.EventType, mwares ...Middleware[websockets.Ctx]) + // Send a message to a specific connection Send(ctx context.Context, connectionId string, message []byte) error + // Close a specific connection Close(ctx context.Context, connectionId string) error } @@ -34,11 +52,11 @@ type websocket struct { Websocket name string - manager Manager + manager *manager client websocketsv1.WebsocketClient } -// NewCollection register this collection as a required resource for the calling function/container. +// NewWebsocket - Create a new Websocket API resource func NewWebsocket(name string) (Websocket, error) { registerResult := <-defaultManager.registerResource(&resourcesv1.ResourceDeclareRequest{ Id: &resourcesv1.ResourceIdentifier{ @@ -52,12 +70,12 @@ func NewWebsocket(name string) (Websocket, error) { actions := []resourcesv1.Action{resourcesv1.Action_WebsocketManage} - m, err := defaultManager.registerPolicy(registerResult.Identifier, actions...) + err := defaultManager.registerPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - wClient := websocketsv1.NewWebsocketClient(m.conn) + wClient := websocketsv1.NewWebsocketClient(defaultManager.conn) return &websocket{ manager: defaultManager, @@ -70,20 +88,6 @@ func (w *websocket) Name() string { return w.name } -// On registers a handler for a specific event type on the websocket -// Valid function signatures for middleware are: -// -// func() -// func() error -// func(*websockets.Ctx) -// func(*websockets.Ctx) error -// func(*websockets.Ctx) *websockets.Ctx -// func(*websockets.Ctx) (*websockets.Ctx, error) -// func(*websockets.Ctx, Handler[websockets.Ctx]) *websockets.Ctx -// func(*websockets.Ctx, Handler[websockets.Ctx]) error -// func(*websockets.Ctx, Handler[websockets.Ctx]) (*websockets.Ctx, error) -// Middleware[websockets.Ctx] -// Handler[websockets.Ctx] func (w *websocket) On(eventType websockets.EventType, middleware ...Middleware[websockets.Ctx]) { var _eventType websocketsv1.WebsocketEventType switch eventType { diff --git a/nitric/websocket_workers.go b/nitric/websocket_workers.go index ed11dcf..4242e80 100644 --- a/nitric/websocket_workers.go +++ b/nitric/websocket_workers.go @@ -21,10 +21,10 @@ import ( "google.golang.org/grpc" - "github.com/nitrictech/go-sdk/api/errors" - "github.com/nitrictech/go-sdk/api/errors/codes" - "github.com/nitrictech/go-sdk/api/websockets" "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + "github.com/nitrictech/go-sdk/nitric/websockets" v1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) diff --git a/api/websockets/context.go b/nitric/websockets/context.go similarity index 100% rename from api/websockets/context.go rename to nitric/websockets/context.go diff --git a/api/websockets/request.go b/nitric/websockets/request.go similarity index 100% rename from api/websockets/request.go rename to nitric/websockets/request.go diff --git a/api/websockets/response.go b/nitric/websockets/response.go similarity index 100% rename from api/websockets/response.go rename to nitric/websockets/response.go From 9ea82bee3fe18484a3c6c1393684d5daba56ca06 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Thu, 19 Sep 2024 11:41:37 +1000 Subject: [PATCH 14/42] allow websockets.On to accept interface --- nitric/websocket.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/nitric/websocket.go b/nitric/websocket.go index 9e2b90d..6f7dc78 100644 --- a/nitric/websocket.go +++ b/nitric/websocket.go @@ -41,7 +41,7 @@ type Websocket interface { // func(*websocket.Ctx, Handler[websocket.Ctx]) (*websocket.Ctx, error) // Middleware[websocket.Ctx] // Handler[websocket.Ctx] - On(eventType websockets.EventType, mwares ...Middleware[websockets.Ctx]) + On(eventType websockets.EventType, mwares ...interface{}) // Send a message to a specific connection Send(ctx context.Context, connectionId string, message []byte) error // Close a specific connection @@ -88,7 +88,7 @@ func (w *websocket) Name() string { return w.name } -func (w *websocket) On(eventType websockets.EventType, middleware ...Middleware[websockets.Ctx]) { +func (w *websocket) On(eventType websockets.EventType, middleware ...interface{}) { var _eventType websocketsv1.WebsocketEventType switch eventType { case websockets.EventType_Disconnect: @@ -103,7 +103,13 @@ func (w *websocket) On(eventType websockets.EventType, middleware ...Middleware[ SocketName: w.name, EventType: _eventType, } - composeHandler := Compose(middleware...) + + middlewares, err := interfacesToMiddleware[websockets.Ctx](middleware) + if err != nil { + panic(err) + } + + composeHandler := Compose(middlewares...) opts := &websocketWorkerOpts{ RegistrationRequest: registrationRequest, From 9caa7aae6e793c9fb11381f897251fe61579180c Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Thu, 19 Sep 2024 12:37:26 +1000 Subject: [PATCH 15/42] fmt --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- nitric/keyvalue/store.go | 3 ++- nitric/queues/queue.go | 3 ++- nitric/secrets/secrets.go | 3 ++- nitric/storage/bucket.go | 7 ++++--- nitric/topic.go | 6 ------ 7 files changed, 31 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index 6014421..bef6532 100644 --- a/go.mod +++ b/go.mod @@ -6,17 +6,17 @@ toolchain go1.23.0 require ( github.com/golang/mock v1.7.0-rc.1 - github.com/golang/protobuf v1.5.3 + github.com/golang/protobuf v1.5.4 github.com/golangci/golangci-lint v1.61.0 github.com/google/addlicense v1.1.1 github.com/missionMeteora/toolkit v0.0.0-20170713173850-88364e3ef8cc - github.com/nitrictech/nitric/core v0.0.0-20240501153359-997c6077b84f + github.com/nitrictech/nitric/core v0.0.0-20240915234849-42c1e482ddab github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.34.2 github.com/uw-labs/lichen v0.1.7 google.golang.org/grpc v1.66.0 - google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 ) require ( @@ -102,7 +102,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mgechev/revive v1.3.9 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect @@ -111,14 +111,14 @@ require ( github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect github.com/nunnatsa/ginkgolinter v0.16.2 // indirect - github.com/nxadm/tail v1.4.8 // indirect + github.com/nxadm/tail v1.4.11 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.6.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect @@ -133,7 +133,7 @@ require ( github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect github.com/securego/gosec/v2 v2.21.2 // indirect - github.com/sergi/go-diff v1.3.1 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect diff --git a/go.sum b/go.sum index 0e0aa45..8da0a9f 100644 --- a/go.sum +++ b/go.sum @@ -237,8 +237,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 h1:/1322Qns6BtQxUZDTAT4SdcoxknUki7IAoK4SAXr8ME= @@ -397,8 +397,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= -github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A= github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU= github.com/missionMeteora/toolkit v0.0.0-20170713173850-88364e3ef8cc h1:/oFlKiuu6L1sIvZ7A363qMhNM+DUQL5WsVe1xIRQnFU= @@ -424,15 +424,16 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nitrictech/nitric/core v0.0.0-20240501153359-997c6077b84f h1:usgb/sRqzHSNcGsC8yIVAmXVdXaE4ZyAwzLzuW5+lag= -github.com/nitrictech/nitric/core v0.0.0-20240501153359-997c6077b84f/go.mod h1:OfaIrPrJJjrFNOOgYbzoBGUblO2DadoXCrloAsUW0H0= +github.com/nitrictech/nitric/core v0.0.0-20240915234849-42c1e482ddab h1:59YTNUa6en385Y21SwMTaixbe31SwgzjkjEhxx0RuwQ= +github.com/nitrictech/nitric/core v0.0.0-20240915234849-42c1e482ddab/go.mod h1:N274XVBjYhGEQoT42baWM6/lETBQYQhqPpqUuk2gmLc= github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf h1:8MB8W8ylM8sCM2COGfiO39/tB6BTdiawLszaUGCNL5w= github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf/go.mod h1:b2lzk2a4o1bvSrSCE6yvTldHuXCJymuDVhdMJGOSslw= github.com/nunnatsa/ginkgolinter v0.16.2 h1:8iLqHIZvN4fTLDC0Ke9tbSZVcyVHoBs0HIbnVSxfHJk= github.com/nunnatsa/ginkgolinter v0.16.2/go.mod h1:4tWRinDN1FeJgU+iJANW/kz7xKN5nYRAOfJDQUS9dOQ= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -478,8 +479,8 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= @@ -526,8 +527,8 @@ github.com/sashamelentyev/usestdlibvars v1.27.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7 github.com/securego/gosec/v2 v2.21.2 h1:deZp5zmYf3TWwU7A7cR2+SolbTpZ3HQiwFqnzQyEl3M= github.com/securego/gosec/v2 v2.21.2/go.mod h1:au33kg78rNseF5PwPnTWhuYBFf534bvJRvOrgZ/bFzU= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -982,8 +983,8 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 h1:TLkBREm4nIsEcexnCjgQd5GQWaHcqMzwQV0TX9pq8S0= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -996,7 +997,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/nitric/keyvalue/store.go b/nitric/keyvalue/store.go index eea2a77..95f3cb2 100644 --- a/nitric/keyvalue/store.go +++ b/nitric/keyvalue/store.go @@ -17,11 +17,12 @@ package keyvalue import ( "context" + "google.golang.org/grpc" + "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/protoutils" - "google.golang.org/grpc" v1 "github.com/nitrictech/nitric/core/pkg/proto/kvstore/v1" ) diff --git a/nitric/queues/queue.go b/nitric/queues/queue.go index 90d67ee..f83862d 100644 --- a/nitric/queues/queue.go +++ b/nitric/queues/queue.go @@ -17,11 +17,12 @@ package queues import ( "context" + "google.golang.org/grpc" + "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/queues/v1" - "google.golang.org/grpc" ) // QueueClientIface is a resource for async enqueueing/dequeueing of messages. diff --git a/nitric/secrets/secrets.go b/nitric/secrets/secrets.go index 04854bb..deadf50 100644 --- a/nitric/secrets/secrets.go +++ b/nitric/secrets/secrets.go @@ -17,11 +17,12 @@ package secrets import ( "context" + "google.golang.org/grpc" + "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" - "google.golang.org/grpc" ) type SecretValue []byte diff --git a/nitric/storage/bucket.go b/nitric/storage/bucket.go index d4456cf..1376356 100644 --- a/nitric/storage/bucket.go +++ b/nitric/storage/bucket.go @@ -18,12 +18,13 @@ import ( "context" "time" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/durationpb" + "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" - "google.golang.org/grpc" - "google.golang.org/protobuf/types/known/durationpb" ) // Cloud storage bucket resource for large file storage. @@ -126,7 +127,7 @@ func WithPresignUrlExpiry(expiry time.Duration) PresignUrlOption { func getPresignUrlOpts(mode Mode, opts ...PresignUrlOption) *presignUrlOptions { defaultOpts := &presignUrlOptions{ mode: mode, - expiry: time.Duration(time.Minute * 5), + expiry: time.Minute * 5, } for _, opt := range opts { diff --git a/nitric/topic.go b/nitric/topic.go index da23fdc..9cbbdca 100644 --- a/nitric/topic.go +++ b/nitric/topic.go @@ -52,12 +52,6 @@ type SubscribableTopic interface { Subscribe(...interface{}) } -type topic struct { - topics.TopicClientIface - - manager *manager -} - type subscribableTopic struct { name string manager *manager From 66861a4ed01b1ba278c0f6984bfc0c64c64a79de Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Thu, 19 Sep 2024 12:37:42 +1000 Subject: [PATCH 16/42] add sql databases --- nitric/sql.go | 59 ++++++++++++++++++++++++++++++++++++++ nitric/sql/sql.go | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 nitric/sql.go create mode 100644 nitric/sql/sql.go diff --git a/nitric/sql.go b/nitric/sql.go new file mode 100644 index 0000000..1a44b0d --- /dev/null +++ b/nitric/sql.go @@ -0,0 +1,59 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 nitric + +import ( + "github.com/nitrictech/go-sdk/nitric/sql" + v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" +) + +type sqlDatabaseOption func(*v1.SqlDatabaseResource) + +func WithMigrationsPath(path string) sqlDatabaseOption { + return func(r *v1.SqlDatabaseResource) { + r.Migrations = &v1.SqlDatabaseMigrations{ + Migrations: &v1.SqlDatabaseMigrations_MigrationsPath{ + MigrationsPath: path, + }, + } + } +} + +// NewSqlDatabase - Create a new Sql Database resource +func NewSqlDatabase(name string, opts ...sqlDatabaseOption) (*sql.SqlClient, error) { + resourceConfig := &v1.ResourceDeclareRequest_SqlDatabase{ + SqlDatabase: &v1.SqlDatabaseResource{}, + } + + for _, opt := range opts { + opt(resourceConfig.SqlDatabase) + } + + registerChan := defaultManager.registerResource(&v1.ResourceDeclareRequest{ + Id: &v1.ResourceIdentifier{ + Type: v1.ResourceType_SqlDatabase, + Name: name, + }, + Config: resourceConfig, + }) + + // Make sure that registerChan is read + // Currently sql databases do not have allow methods so there is no reason to block on this + go func() { + <-registerChan + }() + + return sql.NewSqlClient(name) +} diff --git a/nitric/sql/sql.go b/nitric/sql/sql.go new file mode 100644 index 0000000..202a848 --- /dev/null +++ b/nitric/sql/sql.go @@ -0,0 +1,72 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 sql + +import ( + "context" + + "google.golang.org/grpc" + + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + + v1 "github.com/nitrictech/nitric/core/pkg/proto/sql/v1" +) + +type SqlClientIface interface { + // Name - The name of the store + Name() string + // Get a value from the store + ConnectionString(context.Context) (string, error) +} + +type SqlClient struct { + name string + sqlClient v1.SqlClient +} + +func (s *SqlClient) Name() string { + return s.name +} + +func (s *SqlClient) ConnectionString(ctx context.Context) (string, error) { + resp, err := s.sqlClient.ConnectionString(ctx, &v1.SqlConnectionStringRequest{ + DatabaseName: s.name, + }) + if err != nil { + return "", err + } + + return resp.ConnectionString, nil +} + +func NewSqlClient(name string) (*SqlClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "unable to reach nitric server", + err, + ) + } + + client := v1.NewSqlClient(conn) + + return &SqlClient{ + name: name, + sqlClient: client, + }, nil +} From 356bfaf3059d4ed05504d19a3c0caf0d3cda4610 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Mon, 23 Sep 2024 12:58:56 +1000 Subject: [PATCH 17/42] Add generic middleware composition function --- nitric/api.go | 4 ++-- nitric/bucket.go | 2 +- nitric/middleware.go | 14 ++++++++++++-- nitric/options.go | 4 ++-- nitric/schedule.go | 4 ++-- nitric/topic.go | 2 +- nitric/websocket.go | 2 +- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/nitric/api.go b/nitric/api.go index dd2343d..e6c5cc1 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -55,7 +55,7 @@ type route struct { func composeRouteMiddleware(apiMiddleware Middleware[httpx.Ctx], routeMiddleware []Middleware[httpx.Ctx]) Middleware[httpx.Ctx] { allMiddleware := append([]Middleware[httpx.Ctx]{apiMiddleware}, routeMiddleware...) - return Compose(allMiddleware...) + return ComposeMiddleware(allMiddleware...) } func (a *api) NewRoute(match string, middleware ...Middleware[httpx.Ctx]) Route { @@ -94,7 +94,7 @@ func (r *route) AddMethodHandler(methods []string, middleware interface{}, opts panic(err) } - composedHandler := Compose(r.middleware, mw) + composedHandler := ComposeMiddleware(r.middleware, mw) apiOpts := &apispb.ApiWorkerOptions{ SecurityDisabled: mo.securityDisabled, diff --git a/nitric/bucket.go b/nitric/bucket.go index 4a537ec..d46ef21 100644 --- a/nitric/bucket.go +++ b/nitric/bucket.go @@ -130,7 +130,7 @@ func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter panic(err) } - composedHandler := Compose(middlewares...) + composedHandler := ComposeMiddleware(middlewares...) opts := &bucketEventWorkerOpts{ RegistrationRequest: registrationRequest, diff --git a/nitric/middleware.go b/nitric/middleware.go index ecb9ec0..d12f7b9 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -151,8 +151,18 @@ func (h *middlewareChain[T]) invoke(ctx *T, next Handler[T]) (*T, error) { return h.chain[0].invoke(ctx) } -// Compose - Takes a collection of middleware and composes it into a single middleware function -func Compose[T any](funcs ...Middleware[T]) Middleware[T] { +func Compose[T any](funcs ...interface{}) Middleware[T] { + mwares, err := interfacesToMiddleware[T](funcs) + if err != nil { + return func(ctx *T, next Handler[T]) (*T, error) { + return nil, err + } + } + return ComposeMiddleware(mwares...) +} + +// ComposeMiddleware - Takes a collection of middleware and composes it into a single middleware function +func ComposeMiddleware[T any](funcs ...Middleware[T]) Middleware[T] { mwareChain := &middlewareChain[T]{ chain: []*chainedMiddleware[T]{}, } diff --git a/nitric/options.go b/nitric/options.go index 3a1c50a..1b9a537 100644 --- a/nitric/options.go +++ b/nitric/options.go @@ -47,9 +47,9 @@ func OidcRule(name string, issuer string, audiences []string) SecurityOption { func WithMiddleware(middleware ...Middleware[apis.Ctx]) ApiOption { return func(api *api) { if api.middleware != nil { - api.middleware = Compose(api.middleware, Compose(middleware...)) + api.middleware = ComposeMiddleware(api.middleware, ComposeMiddleware(middleware...)) } else { - api.middleware = Compose(middleware...) + api.middleware = ComposeMiddleware(middleware...) } } } diff --git a/nitric/schedule.go b/nitric/schedule.go index b3a2669..86300c9 100644 --- a/nitric/schedule.go +++ b/nitric/schedule.go @@ -87,7 +87,7 @@ func (s *schedule) Cron(cron string, middleware ...interface{}) { panic(err) } - composeHandler := Compose(middlewares...) + composeHandler := ComposeMiddleware(middlewares...) opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, @@ -118,7 +118,7 @@ func (s *schedule) Every(rate string, middleware ...interface{}) { panic(err) } - composeHandler := Compose(middlewares...) + composeHandler := ComposeMiddleware(middlewares...) opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, diff --git a/nitric/topic.go b/nitric/topic.go index 9cbbdca..3af2513 100644 --- a/nitric/topic.go +++ b/nitric/topic.go @@ -114,7 +114,7 @@ func (t *subscribableTopic) Subscribe(middleware ...interface{}) { panic(err) } - composeHandler := Compose(middlewares...) + composeHandler := ComposeMiddleware(middlewares...) opts := &subscriptionWorkerOpts{ RegistrationRequest: registrationRequest, diff --git a/nitric/websocket.go b/nitric/websocket.go index 6f7dc78..64b6b86 100644 --- a/nitric/websocket.go +++ b/nitric/websocket.go @@ -109,7 +109,7 @@ func (w *websocket) On(eventType websockets.EventType, middleware ...interface{} panic(err) } - composeHandler := Compose(middlewares...) + composeHandler := ComposeMiddleware(middlewares...) opts := &websocketWorkerOpts{ RegistrationRequest: registrationRequest, From 50aa2cf760c1c74e1fb6383f7d26b75b39fb295d Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Mon, 23 Sep 2024 13:15:56 +1000 Subject: [PATCH 18/42] maintain proper middleware order --- nitric/middleware.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/nitric/middleware.go b/nitric/middleware.go index d12f7b9..df2c40a 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -154,9 +154,7 @@ func (h *middlewareChain[T]) invoke(ctx *T, next Handler[T]) (*T, error) { func Compose[T any](funcs ...interface{}) Middleware[T] { mwares, err := interfacesToMiddleware[T](funcs) if err != nil { - return func(ctx *T, next Handler[T]) (*T, error) { - return nil, err - } + panic(err) } return ComposeMiddleware(mwares...) } @@ -164,7 +162,7 @@ func Compose[T any](funcs ...interface{}) Middleware[T] { // ComposeMiddleware - Takes a collection of middleware and composes it into a single middleware function func ComposeMiddleware[T any](funcs ...Middleware[T]) Middleware[T] { mwareChain := &middlewareChain[T]{ - chain: []*chainedMiddleware[T]{}, + chain: make([]*chainedMiddleware[T], len(funcs)), } var nextFunc Handler[T] = nil @@ -178,7 +176,7 @@ func ComposeMiddleware[T any](funcs ...Middleware[T]) Middleware[T] { nextFunc: nextFunc, } nextFunc = cm.invoke - mwareChain.chain = append(mwareChain.chain, cm) + mwareChain.chain[i] = cm } return mwareChain.invoke From 8443ccba4333feaffa5c27140d299715d0276315 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Mon, 23 Sep 2024 13:23:53 +1000 Subject: [PATCH 19/42] exclude empty functions --- nitric/middleware.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/nitric/middleware.go b/nitric/middleware.go index df2c40a..9cd9db8 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -161,18 +161,22 @@ func Compose[T any](funcs ...interface{}) Middleware[T] { // ComposeMiddleware - Takes a collection of middleware and composes it into a single middleware function func ComposeMiddleware[T any](funcs ...Middleware[T]) Middleware[T] { + // remove empty funcs + filteredFuncs := []Middleware[T]{} + for _, f := range funcs { + if f != nil { + filteredFuncs = append(filteredFuncs, f) + } + } + mwareChain := &middlewareChain[T]{ - chain: make([]*chainedMiddleware[T], len(funcs)), + chain: make([]*chainedMiddleware[T], len(filteredFuncs)), } var nextFunc Handler[T] = nil - for i := len(funcs) - 1; i >= 0; i = i - 1 { - if funcs[i] == nil { - continue - } - + for i := len(filteredFuncs) - 1; i >= 0; i = i - 1 { cm := &chainedMiddleware[T]{ - fun: funcs[i], + fun: filteredFuncs[i], nextFunc: nextFunc, } nextFunc = cm.invoke From 8f9227e704ee41a74e160e786e1888f53711ab80 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Mon, 23 Sep 2024 13:31:23 +1000 Subject: [PATCH 20/42] always return original ctx in wrappers --- nitric/middleware.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nitric/middleware.go b/nitric/middleware.go index 9cd9db8..157ce9e 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -68,7 +68,7 @@ func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { handlerType = func(ctx *T, next Handler[T]) (*T, error) { err := typ() if err != nil { - return nil, err + return ctx, err } return next(ctx) } @@ -81,7 +81,7 @@ func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { handlerType = handlerToMware(func(ctx *T) (*T, error) { err := typ(ctx) if err != nil { - return nil, err + return ctx, err } return ctx, nil }) @@ -99,7 +99,7 @@ func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { handlerType = Middleware[T](func(ctx *T, next Handler[T]) (*T, error) { err := typ(ctx, next) if err != nil { - return nil, err + return ctx, err } return next(ctx) }) From 2a1db81ccd25ba16fc4ce71651fba9f51655d9e5 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Mon, 23 Sep 2024 14:04:48 +1000 Subject: [PATCH 21/42] return nil middleware if functions are empty --- nitric/middleware.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nitric/middleware.go b/nitric/middleware.go index 157ce9e..8a486f7 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -169,6 +169,10 @@ func ComposeMiddleware[T any](funcs ...Middleware[T]) Middleware[T] { } } + if len(filteredFuncs) == 0 { + return nil + } + mwareChain := &middlewareChain[T]{ chain: make([]*chainedMiddleware[T], len(filteredFuncs)), } From 25e40b5c5d1e419a9715ef836d4f8860910e9a01 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 24 Sep 2024 11:41:08 +1000 Subject: [PATCH 22/42] fix typos --- nitric/topic.go | 6 +++--- nitric/topic_workers.go | 2 +- nitric/topics/topic.go | 5 ++--- nitric/topics/topic_test.go | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/nitric/topic.go b/nitric/topic.go index 3af2513..3d331e5 100644 --- a/nitric/topic.go +++ b/nitric/topic.go @@ -58,7 +58,7 @@ type subscribableTopic struct { registerChan <-chan RegisterResult } -// NewTopic creates a new Topic with the give permissions. +// NewTopic creates a new Topic with the give name. func NewTopic(name string) SubscribableTopic { topic := &subscribableTopic{ name: name, @@ -114,11 +114,11 @@ func (t *subscribableTopic) Subscribe(middleware ...interface{}) { panic(err) } - composeHandler := ComposeMiddleware(middlewares...) + composedHandler := ComposeMiddleware(middlewares...) opts := &subscriptionWorkerOpts{ RegistrationRequest: registrationRequest, - Middleware: composeHandler, + Middleware: composedHandler, } worker := newSubscriptionWorker(opts) diff --git a/nitric/topic_workers.go b/nitric/topic_workers.go index fa071af..14c10d5 100644 --- a/nitric/topic_workers.go +++ b/nitric/topic_workers.go @@ -93,7 +93,7 @@ func newSubscriptionWorker(opts *subscriptionWorkerOpts) *subscriptionWorker { if err != nil { panic(errors.NewWithCause( codes.Unavailable, - "NewSubscriptionWorker: Unable to reach StorageListenerClient", + "NewSubscriptionWorker: Unable to reach SubscriberClient", err, )) } diff --git a/nitric/topics/topic.go b/nitric/topics/topic.go index d2ca33d..6413cc0 100644 --- a/nitric/topics/topic.go +++ b/nitric/topics/topic.go @@ -56,7 +56,6 @@ func WithDelay(duration time.Duration) func(*v1.TopicPublishRequest) { } func (s *TopicClient) Publish(ctx context.Context, message map[string]interface{}, opts ...PublishOption) error { - // Convert payload to Protobuf Struct payloadStruct, err := protoutils.NewStruct(message) if err != nil { return errors.NewWithCause(codes.InvalidArgument, "Topic.Publish", err) @@ -89,14 +88,14 @@ func NewTopicClient(name string) (*TopicClient, error) { if err != nil { return nil, errors.NewWithCause( codes.Unavailable, - "topic.NewTopic: Unable to reach Nitric server", + "topics.NewTopicClient: Unable to reach Nitric server", err, ) } topicClient := v1.NewTopicsClient(conn) if err != nil { - return nil, errors.NewWithCause(codes.Internal, "NewTopic", err) + return nil, errors.NewWithCause(codes.Internal, "NewTopicClient", err) } return &TopicClient{ diff --git a/nitric/topics/topic_test.go b/nitric/topics/topic_test.go index 398fee7..9331d9d 100644 --- a/nitric/topics/topic_test.go +++ b/nitric/topics/topic_test.go @@ -28,7 +28,7 @@ import ( "github.com/nitrictech/protoutils" ) -var _ = Describe("File", func() { +var _ = Describe("Topic", func() { var ( ctrl *gomock.Controller mockTopic *mock_v1.MockTopicsClient From f6e9756b97cd1175abfb2c49344ee8dab0660081 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 24 Sep 2024 12:02:05 +1000 Subject: [PATCH 23/42] fix typos and clean up old code --- nitric/bucket.go | 6 +++--- nitric/keyvalue/store.go | 2 +- nitric/queues/message.go | 2 +- nitric/queues/queue.go | 2 +- nitric/schedule_workers.go | 2 +- nitric/secrets/secrets.go | 2 +- nitric/secrets/secrets_test.go | 2 +- nitric/storage/bucket.go | 28 ++++++++++++++-------------- nitric/storage/bucket_test.go | 4 ++-- nitric/topics/topic.go | 5 +---- nitric/websocket_workers.go | 2 +- 11 files changed, 27 insertions(+), 30 deletions(-) diff --git a/nitric/bucket.go b/nitric/bucket.go index d46ef21..e1486a0 100644 --- a/nitric/bucket.go +++ b/nitric/bucket.go @@ -33,7 +33,7 @@ type bucket struct { type Bucket interface { // Allow requests the given permissions to the bucket. - Allow(BucketPermission, ...BucketPermission) (*storage.Bucket, error) + Allow(BucketPermission, ...BucketPermission) (*storage.BucketClient, error) // On registers a handler for a specific event type on the bucket. // Valid function signatures for middleware are: @@ -80,7 +80,7 @@ func NewBucket(name string) Bucket { return bucket } -func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) (*storage.Bucket, error) { +func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) (*storage.BucketClient, error) { allPerms := append([]BucketPermission{permission}, permissions...) actions := []v1.Action{} @@ -107,7 +107,7 @@ func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermiss return nil, err } - return storage.NewBucket(b.name) + return storage.NewBucketClient(b.name) } func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter string, middleware ...interface{}) { diff --git a/nitric/keyvalue/store.go b/nitric/keyvalue/store.go index 95f3cb2..538c0e3 100644 --- a/nitric/keyvalue/store.go +++ b/nitric/keyvalue/store.go @@ -165,7 +165,7 @@ func NewKvStoreClient(name string) (*KvStoreClient, error) { if err != nil { return nil, errors.NewWithCause( codes.Unavailable, - "unable to reach nitric server", + "NewKvStoreClient: unable to reach nitric server", err, ) } diff --git a/nitric/queues/message.go b/nitric/queues/message.go index 0fa21e7..0da38b7 100644 --- a/nitric/queues/message.go +++ b/nitric/queues/message.go @@ -69,7 +69,7 @@ func messageToWire(message map[string]interface{}) (*v1.QueueMessage, error) { if err != nil { return nil, errors.NewWithCause( codes.Internal, - "messageToWire: failed to serialize payload: %s", + "messageToWire: failed to serialize message: %s", err, ) } diff --git a/nitric/queues/queue.go b/nitric/queues/queue.go index f83862d..93a24de 100644 --- a/nitric/queues/queue.go +++ b/nitric/queues/queue.go @@ -112,7 +112,7 @@ func NewQueueClient(name string) (*QueueClient, error) { if err != nil { return nil, errors.NewWithCause( codes.Unavailable, - "unable to reach nitric server", + "NewQueueClient: unable to reach nitric server", err, ) } diff --git a/nitric/schedule_workers.go b/nitric/schedule_workers.go index e2104ff..e46511f 100644 --- a/nitric/schedule_workers.go +++ b/nitric/schedule_workers.go @@ -92,7 +92,7 @@ func newScheduleWorker(opts *scheduleWorkerOpts) *scheduleWorker { if err != nil { panic(errors.NewWithCause( codes.Unavailable, - "NewIntervalWorker: Unable to reach StorageListenerClient", + "NewScheduleWorker: Unable to reach SchedulesClient", err, )) } diff --git a/nitric/secrets/secrets.go b/nitric/secrets/secrets.go index deadf50..ea5d628 100644 --- a/nitric/secrets/secrets.go +++ b/nitric/secrets/secrets.go @@ -99,7 +99,7 @@ func NewSecretClient(name string) (*SecretClient, error) { if err != nil { return nil, errors.NewWithCause( codes.Unavailable, - "unable to reach nitric server", + "NewSecretClient: unable to reach nitric server", err, ) } diff --git a/nitric/secrets/secrets_test.go b/nitric/secrets/secrets_test.go index 171d4c6..cf36fc2 100644 --- a/nitric/secrets/secrets_test.go +++ b/nitric/secrets/secrets_test.go @@ -27,7 +27,7 @@ import ( v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" ) -var _ = Describe("secretRefImpl", func() { +var _ = Describe("Secret", func() { var ( ctrl *gomock.Controller mockSC *mock_v1.MockSecretManagerClient diff --git a/nitric/storage/bucket.go b/nitric/storage/bucket.go index 1376356..142e500 100644 --- a/nitric/storage/bucket.go +++ b/nitric/storage/bucket.go @@ -28,7 +28,7 @@ import ( ) // Cloud storage bucket resource for large file storage. -type BucketIface interface { +type BucketClientIface interface { // Name - Get the name of the bucket Name() string // ListFiles - List the files in the bucket @@ -45,14 +45,14 @@ type BucketIface interface { DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) } -var _ BucketIface = (*Bucket)(nil) +var _ BucketClientIface = (*BucketClient)(nil) -type Bucket struct { +type BucketClient struct { storageClient v1.StorageClient name string } -func (o *Bucket) Read(ctx context.Context, key string) ([]byte, error) { +func (o *BucketClient) Read(ctx context.Context, key string) ([]byte, error) { r, err := o.storageClient.Read(ctx, &v1.StorageReadRequest{ BucketName: o.name, Key: key, @@ -64,7 +64,7 @@ func (o *Bucket) Read(ctx context.Context, key string) ([]byte, error) { return r.GetBody(), nil } -func (o *Bucket) Write(ctx context.Context, key string, content []byte) error { +func (o *BucketClient) Write(ctx context.Context, key string, content []byte) error { if _, err := o.storageClient.Write(ctx, &v1.StorageWriteRequest{ BucketName: o.name, Key: key, @@ -76,7 +76,7 @@ func (o *Bucket) Write(ctx context.Context, key string, content []byte) error { return nil } -func (o *Bucket) Delete(ctx context.Context, key string) error { +func (o *BucketClient) Delete(ctx context.Context, key string) error { if _, err := o.storageClient.Delete(ctx, &v1.StorageDeleteRequest{ BucketName: o.name, Key: key, @@ -87,7 +87,7 @@ func (o *Bucket) Delete(ctx context.Context, key string) error { return nil } -func (b *Bucket) ListFiles(ctx context.Context) ([]string, error) { +func (b *BucketClient) ListFiles(ctx context.Context) ([]string, error) { resp, err := b.storageClient.ListBlobs(ctx, &v1.StorageListBlobsRequest{ BucketName: b.name, }) @@ -137,19 +137,19 @@ func getPresignUrlOpts(mode Mode, opts ...PresignUrlOption) *presignUrlOptions { return defaultOpts } -func (o *Bucket) UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { +func (o *BucketClient) UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { optsWithDefaults := getPresignUrlOpts(ModeWrite, opts...) return o.signUrl(ctx, key, optsWithDefaults) } -func (o *Bucket) DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { +func (o *BucketClient) DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { optsWithDefaults := getPresignUrlOpts(ModeRead, opts...) return o.signUrl(ctx, key, optsWithDefaults) } -func (o *Bucket) signUrl(ctx context.Context, key string, opts *presignUrlOptions) (string, error) { +func (o *BucketClient) signUrl(ctx context.Context, key string, opts *presignUrlOptions) (string, error) { op := v1.StoragePreSignUrlRequest_READ if opts.mode == ModeWrite { @@ -169,23 +169,23 @@ func (o *Bucket) signUrl(ctx context.Context, key string, opts *presignUrlOption return r.Url, nil } -func (b *Bucket) Name() string { +func (b *BucketClient) Name() string { return b.name } -func NewBucket(name string) (*Bucket, error) { +func NewBucketClient(name string) (*BucketClient, error) { conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) if err != nil { return nil, errors.NewWithCause( codes.Unavailable, - "unable to reach nitric server", + "NewBucketClient: unable to reach nitric server", err, ) } storageClient := v1.NewStorageClient(conn) - return &Bucket{ + return &BucketClient{ name: name, storageClient: storageClient, }, nil diff --git a/nitric/storage/bucket_test.go b/nitric/storage/bucket_test.go index 4ac641b..c154334 100644 --- a/nitric/storage/bucket_test.go +++ b/nitric/storage/bucket_test.go @@ -31,7 +31,7 @@ var _ = Describe("Bucket", func() { var ( ctrl *gomock.Controller mockStorage *mock_v1.MockStorageClient - bucket *Bucket + bucket *BucketClient bucketName string ctx context.Context ) @@ -42,7 +42,7 @@ var _ = Describe("Bucket", func() { bucketName = "test-bucket" - bucket = &Bucket{ + bucket = &BucketClient{ name: bucketName, storageClient: mockStorage, } diff --git a/nitric/topics/topic.go b/nitric/topics/topic.go index 6413cc0..a256b82 100644 --- a/nitric/topics/topic.go +++ b/nitric/topics/topic.go @@ -88,15 +88,12 @@ func NewTopicClient(name string) (*TopicClient, error) { if err != nil { return nil, errors.NewWithCause( codes.Unavailable, - "topics.NewTopicClient: Unable to reach Nitric server", + "NewTopicClient: unable to reach nitric server", err, ) } topicClient := v1.NewTopicsClient(conn) - if err != nil { - return nil, errors.NewWithCause(codes.Internal, "NewTopicClient", err) - } return &TopicClient{ name: name, diff --git a/nitric/websocket_workers.go b/nitric/websocket_workers.go index 4242e80..6d2bb2a 100644 --- a/nitric/websocket_workers.go +++ b/nitric/websocket_workers.go @@ -92,7 +92,7 @@ func newWebsocketWorker(opts *websocketWorkerOpts) *websocketWorker { if err != nil { panic(errors.NewWithCause( codes.Unavailable, - "NewWebsocketWorker: Unable to reach StorageListenerClient", + "NewWebsocketWorker: Unable to reach WebsocketHandlerClient", err, )) } From 661ac5594a71b48f0db375f6bf9f66e9837902c5 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 25 Sep 2024 18:53:37 +1000 Subject: [PATCH 24/42] don't return nil ctx --- nitric/middleware.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nitric/middleware.go b/nitric/middleware.go index 8a486f7..28d0562 100644 --- a/nitric/middleware.go +++ b/nitric/middleware.go @@ -134,6 +134,14 @@ func (c *chainedMiddleware[T]) invoke(ctx *T) (*T, error) { c.nextFunc = dummyHandler[T] } + outCtx, err := c.fun(ctx, c.nextFunc) + + // The returned context should never be nil, since it's used to create the response. + // If it is, return the current context and the error + if outCtx == nil { + return ctx, err + } + return c.fun(ctx, c.nextFunc) } From a54abd99e4c52bc627108a243f344103d5fb3d91 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 1 Oct 2024 13:43:26 +1000 Subject: [PATCH 25/42] remove middleware from SDK middleware can be implement using decorators --- nitric/api.go | 85 ++++----------- nitric/api_workers.go | 10 +- nitric/bucket.go | 22 ++-- nitric/bucket_workers.go | 10 +- nitric/handler.go | 58 +++++++++++ nitric/handler_test.go | 75 ++++++++++++++ nitric/manager_test.go | 75 -------------- nitric/middleware.go | 199 ------------------------------------ nitric/middleware_test.go | 125 ---------------------- nitric/options.go | 14 --- nitric/schedule.go | 40 +++----- nitric/schedule_workers.go | 10 +- nitric/topic.go | 18 +--- nitric/topic_workers.go | 10 +- nitric/websocket.go | 18 +--- nitric/websocket_workers.go | 10 +- 16 files changed, 207 insertions(+), 572 deletions(-) create mode 100644 nitric/handler.go create mode 100644 nitric/handler_test.go delete mode 100644 nitric/manager_test.go delete mode 100644 nitric/middleware.go delete mode 100644 nitric/middleware_test.go diff --git a/nitric/api.go b/nitric/api.go index e6c5cc1..0ac3c9c 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -46,26 +46,19 @@ type Route interface { } type route struct { - path string - api *api - middleware Middleware[httpx.Ctx] - manager *manager + path string + api *api + handler Handler[httpx.Ctx] + manager *manager } -func composeRouteMiddleware(apiMiddleware Middleware[httpx.Ctx], routeMiddleware []Middleware[httpx.Ctx]) Middleware[httpx.Ctx] { - allMiddleware := append([]Middleware[httpx.Ctx]{apiMiddleware}, routeMiddleware...) - - return ComposeMiddleware(allMiddleware...) -} - -func (a *api) NewRoute(match string, middleware ...Middleware[httpx.Ctx]) Route { +func (a *api) NewRoute(match string) Route { r, ok := a.routes[match] if !ok { r = &route{ - manager: a.manager, - path: path.Join(a.path, match), - api: a, - middleware: composeRouteMiddleware(a.middleware, middleware), + manager: a.manager, + path: path.Join(a.path, match), + api: a, } } @@ -76,7 +69,7 @@ func (r *route) ApiName() string { return r.api.name } -func (r *route) AddMethodHandler(methods []string, middleware interface{}, opts ...MethodOption) error { +func (r *route) AddMethodHandler(methods []string, handler interface{}, opts ...MethodOption) error { bName := path.Join(r.api.name, r.path, strings.Join(methods, "-")) // default methodOptions will contain OidcOptions passed to API instance and securityDisabled to false @@ -89,13 +82,11 @@ func (r *route) AddMethodHandler(methods []string, middleware interface{}, opts o(mo) } - mw, err := interfaceToMiddleware[httpx.Ctx](middleware) + typedHandler, err := interfaceToHandler[httpx.Ctx](handler) if err != nil { panic(err) } - composedHandler := ComposeMiddleware(r.middleware, mw) - apiOpts := &apispb.ApiWorkerOptions{ SecurityDisabled: mo.securityDisabled, Security: map[string]*apispb.ApiWorkerScopes{}, @@ -123,7 +114,7 @@ func (r *route) AddMethodHandler(methods []string, middleware interface{}, opts wkr := newApiWorker(&apiWorkerOpts{ RegistrationRequest: registrationRequest, - Middleware: composedHandler, + Handler: typedHandler, }) r.manager.addWorker("route:"+bName, wkr) @@ -163,7 +154,7 @@ func (r *route) Options(handler interface{}, opts ...MethodOption) { // path is the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' // handler the handler to register for callbacks. // -// Note: to chain middleware use handler.ComposeHttpMiddlware() +// Note: to chain handler use handler.ComposeHttpMiddlware() type Api interface { // Get adds a Get method handler to the path with any specified opts. // Valid function signatures: @@ -172,12 +163,6 @@ type Api interface { // func() error // func(*apis.Ctx) // func(*apis.Ctx) error - // func(*apis.Ctx) *apis.Ctx - // func(*apis.Ctx) (*apis.Ctx, error) - // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx - // func(*apis.Ctx, Handler[apis.Ctx]) error - // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) - // Middleware[apis.Ctx] // Handler[apis.Ctx] Get(path string, handler interface{}, opts ...MethodOption) // Put adds a Put method handler to the path with any specified opts. @@ -187,12 +172,6 @@ type Api interface { // func() error // func(*apis.Ctx) // func(*apis.Ctx) error - // func(*apis.Ctx) *apis.Ctx - // func(*apis.Ctx) (*apis.Ctx, error) - // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx - // func(*apis.Ctx, Handler[apis.Ctx]) error - // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) - // Middleware[apis.Ctx] // Handler[apis.Ctx] Put(path string, handler interface{}, opts ...MethodOption) // Patch adds a Patch method handler to the path with any specified opts. @@ -202,12 +181,6 @@ type Api interface { // func() error // func(*apis.Ctx) // func(*apis.Ctx) error - // func(*apis.Ctx) *apis.Ctx - // func(*apis.Ctx) (*apis.Ctx, error) - // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx - // func(*apis.Ctx, Handler[apis.Ctx]) error - // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) - // Middleware[apis.Ctx] // Handler[apis.Ctx] Patch(path string, handler interface{}, opts ...MethodOption) // Post adds a Post method handler to the path with any specified opts. @@ -217,12 +190,6 @@ type Api interface { // func() error // func(*apis.Ctx) // func(*apis.Ctx) error - // func(*apis.Ctx) *apis.Ctx - // func(*apis.Ctx) (*apis.Ctx, error) - // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx - // func(*apis.Ctx, Handler[apis.Ctx]) error - // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) - // Middleware[apis.Ctx] // Handler[apis.Ctx] Post(path string, handler interface{}, opts ...MethodOption) // Delete adds a Delete method handler to the path with any specified opts. @@ -232,12 +199,6 @@ type Api interface { // func() error // func(*apis.Ctx) // func(*apis.Ctx) error - // func(*apis.Ctx) *apis.Ctx - // func(*apis.Ctx) (*apis.Ctx, error) - // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx - // func(*apis.Ctx, Handler[apis.Ctx]) error - // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) - // Middleware[apis.Ctx] // Handler[apis.Ctx] Delete(path string, handler interface{}, opts ...MethodOption) // Options adds a Options method handler to the path with any specified opts. @@ -247,16 +208,10 @@ type Api interface { // func() error // func(*apis.Ctx) // func(*apis.Ctx) error - // func(*apis.Ctx) *apis.Ctx - // func(*apis.Ctx) (*apis.Ctx, error) - // func(*apis.Ctx, Handler[apis.Ctx]) *apis.Ctx - // func(*apis.Ctx, Handler[apis.Ctx]) error - // func(*apis.Ctx, Handler[apis.Ctx]) (*apis.Ctx, error) - // Middleware[apis.Ctx] // Handler[apis.Ctx] Options(path string, handler interface{}, opts ...MethodOption) // NewRoute creates a new Route object for the given path. - NewRoute(path string, middleware ...Middleware[httpx.Ctx]) Route + NewRoute(path string) Route } type ApiDetails struct { @@ -271,7 +226,7 @@ type api struct { securityRules map[string]interface{} security []OidcOptions path string - middleware Middleware[httpx.Ctx] + handler Handler[httpx.Ctx] } // NewApi Registers a new API Resource. @@ -325,7 +280,7 @@ func NewApi(name string, opts ...ApiOption) (Api, error) { } // Get adds a Get method handler to the path with any specified opts. -// Note: to chain middleware use handler.ComposeHttpMiddlware() +// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Get(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -334,7 +289,7 @@ func (a *api) Get(match string, handler interface{}, opts ...MethodOption) { } // Post adds a Post method handler to the path with any specified opts. -// Note: to chain middleware use handler.ComposeHttpMiddlware() +// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Post(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -343,7 +298,7 @@ func (a *api) Post(match string, handler interface{}, opts ...MethodOption) { } // Patch adds a Patch method handler to the path with any specified opts. -// Note: to chain middleware use handler.ComposeHttpMiddlware() +// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Patch(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -352,7 +307,7 @@ func (a *api) Patch(match string, handler interface{}, opts ...MethodOption) { } // Put adds a Put method handler to the path with any specified opts. -// Note: to chain middleware use handler.ComposeHttpMiddlware() +// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Put(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -361,7 +316,7 @@ func (a *api) Put(match string, handler interface{}, opts ...MethodOption) { } // Delete adds a Delete method handler to the path with any specified opts. -// Note: to chain middleware use handler.ComposeHttpMiddlware() +// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Delete(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -370,7 +325,7 @@ func (a *api) Delete(match string, handler interface{}, opts ...MethodOption) { } // Options adds an Options method handler to the path with any specified opts. -// Note: to chain middleware use handler.ComposeHttpMiddlware() +// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Options(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) diff --git a/nitric/api_workers.go b/nitric/api_workers.go index 5b70d86..ace8f0b 100644 --- a/nitric/api_workers.go +++ b/nitric/api_workers.go @@ -30,13 +30,13 @@ import ( type apiWorker struct { client v1.ApiClient - middleware Middleware[httpx.Ctx] + Handler Handler[httpx.Ctx] registrationRequest *v1.RegistrationRequest } type apiWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware Middleware[httpx.Ctx] + Handler Handler[httpx.Ctx] } var _ streamWorker = (*apiWorker)(nil) @@ -72,11 +72,11 @@ func (a *apiWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Do nothing + // There is no need to respond to the registration response } else if err == nil && resp.GetHttpRequest() != nil { ctx = httpx.NewCtx(resp) - ctx, err = a.middleware(ctx, dummyHandler) + err = a.Handler(ctx) if err != nil { ctx.WithError(err) } @@ -106,6 +106,6 @@ func newApiWorker(opts *apiWorkerOpts) *apiWorker { return &apiWorker{ client: client, registrationRequest: opts.RegistrationRequest, - middleware: opts.Middleware, + Handler: opts.Handler, } } diff --git a/nitric/bucket.go b/nitric/bucket.go index e1486a0..5ae3b75 100644 --- a/nitric/bucket.go +++ b/nitric/bucket.go @@ -36,20 +36,14 @@ type Bucket interface { Allow(BucketPermission, ...BucketPermission) (*storage.BucketClient, error) // On registers a handler for a specific event type on the bucket. - // Valid function signatures for middleware are: + // Valid function signatures for handler are: // // func() // func() error // func(*storage.Ctx) // func(*storage.Ctx) error - // func(*storage.Ctx) *storage.Ctx - // func(*storage.Ctx) (*storage.Ctx, error) - // func(*storage.Ctx, Handler[storage.Ctx]) *storage.Ctx - // func(*storage.Ctx, Handler[storage.Ctx]) error - // func(*storage.Ctx, Handler[storage.Ctx]) (*storage.Ctx, error) - // Middleware[storage.Ctx] // Handler[storage.Ctx] - On(storage.EventType, string, ...interface{}) + On(eventType storage.EventType, notificationPrefixFilter string, handler interface{}) } const ( @@ -110,9 +104,9 @@ func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermiss return storage.NewBucketClient(b.name) } -func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter string, middleware ...interface{}) { +func (b *bucket) On(eventType storage.EventType, notificationPrefixFilter string, handler interface{}) { var blobEventType storagepb.BlobEventType - switch notificationType { + switch eventType { case storage.WriteNotification: blobEventType = storagepb.BlobEventType_Created case storage.DeleteNotification: @@ -125,21 +119,19 @@ func (b *bucket) On(notificationType storage.EventType, notificationPrefixFilter KeyPrefixFilter: notificationPrefixFilter, } - middlewares, err := interfacesToMiddleware[storage.Ctx](middleware) + typedHandler, err := interfaceToHandler[storage.Ctx](handler) if err != nil { panic(err) } - composedHandler := ComposeMiddleware(middlewares...) - opts := &bucketEventWorkerOpts{ RegistrationRequest: registrationRequest, - Middleware: composedHandler, + Handler: typedHandler, } worker := newBucketEventWorker(opts) b.manager.addWorker("bucketNotification:"+strings.Join([]string{ - b.name, notificationPrefixFilter, string(notificationType), + b.name, notificationPrefixFilter, string(eventType), }, "-"), worker) } diff --git a/nitric/bucket_workers.go b/nitric/bucket_workers.go index a5634e6..30ad379 100644 --- a/nitric/bucket_workers.go +++ b/nitric/bucket_workers.go @@ -31,11 +31,11 @@ import ( type bucketEventWorker struct { client v1.StorageListenerClient registrationRequest *v1.RegistrationRequest - middleware Middleware[storage.Ctx] + handler Handler[storage.Ctx] } type bucketEventWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware Middleware[storage.Ctx] + Handler Handler[storage.Ctx] } // Start implements Worker. @@ -69,10 +69,10 @@ func (b *bucketEventWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Do nothing + // There is no need to respond to the registration response } else if err == nil && resp.GetBlobEventRequest() != nil { ctx = storage.NewCtx(resp) - ctx, err = b.middleware(ctx, dummyHandler) + err = b.handler(ctx) if err != nil { ctx.WithError(err) } @@ -102,6 +102,6 @@ func newBucketEventWorker(opts *bucketEventWorkerOpts) *bucketEventWorker { return &bucketEventWorker{ client: client, registrationRequest: opts.RegistrationRequest, - middleware: opts.Middleware, + handler: opts.Handler, } } diff --git a/nitric/handler.go b/nitric/handler.go new file mode 100644 index 0000000..2deaea4 --- /dev/null +++ b/nitric/handler.go @@ -0,0 +1,58 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 nitric + +import "fmt" + +type ( + Handler[T any] func(context *T) error +) + +// interfaceToHandler - Converts a function to a Handler +// Valid function types are: +// func() +// func() error +// func(*T) +// func(*T) error +// func(*T) *T +// func(*T) (*T, error) +// Handler[T] +// If the function is not a valid type, an error is returned +func interfaceToHandler[T any](handler interface{}) (Handler[T], error) { + var typedHandler Handler[T] + switch handlerType := handler.(type) { + case func(): + typedHandler = func(ctx *T) error { + handlerType() + return nil + } + case func() error: + typedHandler = func(ctx *T) error { + return handlerType() + } + case func(*T): + typedHandler = func(ctx *T) error { + handlerType(ctx) + return nil + } + case Handler[T]: + typedHandler = handlerType + + default: + return nil, fmt.Errorf("invalid handler type: %T", handler) + } + + return typedHandler, nil +} diff --git a/nitric/handler_test.go b/nitric/handler_test.go new file mode 100644 index 0000000..2432341 --- /dev/null +++ b/nitric/handler_test.go @@ -0,0 +1,75 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 nitric + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("handler", func() { + // func() + // func() error + // func(*T) + // func(*T) error + // func(*T, Handler[T]) error + // Handler[T] + Context("interfaceToHandler", func() { + When("interface{} is func()", func() { + It("should return a valid handler", func() { + handler, err := interfaceToHandler[any](func() {}) + + Expect(err).To(BeNil()) + Expect(handler).ToNot(BeNil()) + }) + }) + + When("interface{} is func() error", func() { + It("should return a valid handler", func() { + handler, err := interfaceToHandler[any](func() error { return nil }) + + Expect(err).To(BeNil()) + Expect(handler).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T)", func() { + It("should return a valid handler", func() { + handler, err := interfaceToHandler[string](func(*string) {}) + + Expect(err).To(BeNil()) + Expect(handler).ToNot(BeNil()) + }) + }) + + When("interface{} is func(*T) error", func() { + It("should return a valid handler", func() { + handler, err := interfaceToHandler[string](func(*string) error { return nil }) + + Expect(err).To(BeNil()) + Expect(handler).ToNot(BeNil()) + }) + }) + + When("interface{} is not a valid type", func() { + It("should return an error", func() { + handler, err := interfaceToHandler[string](func() (error, error) { return nil, nil }) + + Expect(err).ToNot(BeNil()) + Expect(handler).To(BeNil()) + }) + }) + }) +}) diff --git a/nitric/manager_test.go b/nitric/manager_test.go deleted file mode 100644 index bd946a6..0000000 --- a/nitric/manager_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -// import ( -// "errors" -// "io" - -// . "github.com/onsi/ginkgo" -// . "github.com/onsi/gomega" - -// apierrors "github.com/nitrictech/go-sdk/nitric/errors" -// ) - -// var _ = Describe("manager", func() { -// Context("isEOF", func() { -// When("is nil", func() { -// got := isEOF(nil) -// It("should be false", func() { -// Expect(got).To(Equal(false)) -// }) -// }) - -// When("is EOF wrapped in ApiError", func() { -// err := apierrors.NewWithCause(500, "unknown", io.EOF) -// got := isEOF(err) -// It("should be true", func() { -// Expect(got).To(Equal(true)) -// }) -// }) - -// When("is an ApiError with nil cause", func() { -// err := apierrors.New(500, "unknown") -// got := isEOF(err) -// It("should be false", func() { -// Expect(got).To(Equal(false)) -// }) -// }) - -// When("is EOF string wrapped in ApiError", func() { -// err := apierrors.NewWithCause(500, "unknown", errors.New("EOF")) -// got := isEOF(err) -// It("should be true", func() { -// Expect(got).To(Equal(true)) -// }) -// }) - -// When("is unexpectedEOF wrapped in ApiError", func() { -// err := apierrors.NewWithCause(500, "unknown", io.ErrUnexpectedEOF) -// got := isEOF(err) -// It("should be false", func() { -// Expect(got).To(Equal(false)) -// }) -// }) - -// When("is native EOF", func() { -// got := isEOF(io.EOF) -// It("should be true", func() { -// Expect(got).To(Equal(true)) -// }) -// }) -// }) -// }) diff --git a/nitric/middleware.go b/nitric/middleware.go deleted file mode 100644 index 28d0562..0000000 --- a/nitric/middleware.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2023 Nitric Technologies Pty Ltd. -// -// 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 nitric - -import "fmt" - -type ( - Handler[T any] func(context *T) (*T, error) - Middleware[T any] func(context *T, next Handler[T]) (*T, error) -) - -type chainedMiddleware[T any] struct { - fun Middleware[T] - nextFunc Handler[T] -} - -func dummyHandler[T any](ctx *T) (*T, error) { - return ctx, nil -} - -func interfacesToMiddleware[T any](mws []interface{}) ([]Middleware[T], error) { - mwares := make([]Middleware[T], len(mws)) - for i, mw := range mws { - mware, err := interfaceToMiddleware[T](mw) - if err != nil { - return nil, err - } - mwares[i] = mware - } - return mwares, nil -} - -// interfaceToMiddleware - Converts a function to a Middleware -// Valid function types are: -// func() -// func() error -// func(*T) -// func(*T) error -// func(*T) *T -// func(*T) (*T, error) -// func(*T, Handler[T]) *T -// func(*T, Handler[T]) error -// func(*T, Handler[T]) (*T, error) -// Middleware[T] -// Handler[T] -// If the function is not a valid type, an error is returned -func interfaceToMiddleware[T any](mw interface{}) (Middleware[T], error) { - var handlerType Middleware[T] - switch typ := mw.(type) { - case func(): - handlerType = func(ctx *T, next Handler[T]) (*T, error) { - typ() - return next(ctx) - } - case func() error: - handlerType = func(ctx *T, next Handler[T]) (*T, error) { - err := typ() - if err != nil { - return ctx, err - } - return next(ctx) - } - case func(*T): - handlerType = handlerToMware(func(ctx *T) (*T, error) { - typ(ctx) - return ctx, nil - }) - case func(*T) error: - handlerType = handlerToMware(func(ctx *T) (*T, error) { - err := typ(ctx) - if err != nil { - return ctx, err - } - return ctx, nil - }) - case func(*T) *T: - handlerType = handlerToMware(func(ctx *T) (*T, error) { - return typ(ctx), nil - }) - case func(*T) (*T, error): - handlerType = handlerToMware(typ) - case func(*T, Handler[T]) *T: - handlerType = Middleware[T](func(ctx *T, next Handler[T]) (*T, error) { - return typ(ctx, next), nil - }) - case func(*T, Handler[T]) error: - handlerType = Middleware[T](func(ctx *T, next Handler[T]) (*T, error) { - err := typ(ctx, next) - if err != nil { - return ctx, err - } - return next(ctx) - }) - case func(*T, Handler[T]) (*T, error): - handlerType = Middleware[T](typ) - case Middleware[T]: - handlerType = typ - case Handler[T]: - handlerType = handlerToMware(typ) - - default: - return nil, fmt.Errorf("invalid middleware type: %T", mw) - } - - return handlerType, nil -} - -func handlerToMware[T any](h Handler[T]) Middleware[T] { - return func(ctx *T, next Handler[T]) (*T, error) { - ctx, err := h(ctx) - if err == nil { - return next(ctx) - } - return nil, err - } -} - -func (c *chainedMiddleware[T]) invoke(ctx *T) (*T, error) { - // Chains are left open-ended so middleware can continue to be linked - // If the chain is incomplete, set a chained dummy handler for safety - if c.nextFunc == nil { - c.nextFunc = dummyHandler[T] - } - - outCtx, err := c.fun(ctx, c.nextFunc) - - // The returned context should never be nil, since it's used to create the response. - // If it is, return the current context and the error - if outCtx == nil { - return ctx, err - } - - return c.fun(ctx, c.nextFunc) -} - -type middlewareChain[T any] struct { - chain []*chainedMiddleware[T] -} - -func (h *middlewareChain[T]) invoke(ctx *T, next Handler[T]) (*T, error) { - if len(h.chain) == 0 { - return nil, fmt.Errorf("there are no middleware in this chain") - } - // Complete the chain - h.chain[len(h.chain)-1].nextFunc = next - - return h.chain[0].invoke(ctx) -} - -func Compose[T any](funcs ...interface{}) Middleware[T] { - mwares, err := interfacesToMiddleware[T](funcs) - if err != nil { - panic(err) - } - return ComposeMiddleware(mwares...) -} - -// ComposeMiddleware - Takes a collection of middleware and composes it into a single middleware function -func ComposeMiddleware[T any](funcs ...Middleware[T]) Middleware[T] { - // remove empty funcs - filteredFuncs := []Middleware[T]{} - for _, f := range funcs { - if f != nil { - filteredFuncs = append(filteredFuncs, f) - } - } - - if len(filteredFuncs) == 0 { - return nil - } - - mwareChain := &middlewareChain[T]{ - chain: make([]*chainedMiddleware[T], len(filteredFuncs)), - } - - var nextFunc Handler[T] = nil - for i := len(filteredFuncs) - 1; i >= 0; i = i - 1 { - cm := &chainedMiddleware[T]{ - fun: filteredFuncs[i], - nextFunc: nextFunc, - } - nextFunc = cm.invoke - mwareChain.chain[i] = cm - } - - return mwareChain.invoke -} diff --git a/nitric/middleware_test.go b/nitric/middleware_test.go deleted file mode 100644 index 081dc1d..0000000 --- a/nitric/middleware_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("middleware", func() { - // func() - // func() error - // func(*T) - // func(*T) error - // func(*T) *T - // func(*T) (*T, error) - // func(*T, Handler[T]) *T - // func(*T, Handler[T]) error - // func(*T, Handler[T]) (*T, error) - // Middleware[T] - // Handler[T] - Context("interfaceToMiddleware", func() { - When("interface{} is func()", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[any](func() {}) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func() error", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[any](func() error { return nil }) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func(*T)", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[string](func(*string) {}) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func(*T) error", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[string](func(*string) error { return nil }) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func(*T) *T", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[string](func(str *string) *string { return str }) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func(*T) (*T, error)", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[string](func(str *string) (*string, error) { return str, nil }) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func(*T, Handler[T]) *T", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[string](func(str *string, next Handler[string]) *string { return str }) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func(*T, Handler[T]) error", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[string](func(str *string, next Handler[string]) error { return nil }) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is func(*T, Handler[T]) (*T, error)", func() { - It("should return a valid middleware", func() { - mw, err := interfaceToMiddleware[string](func(str *string, next Handler[string]) (*string, error) { return str, nil }) - - Expect(err).To(BeNil()) - Expect(mw).ToNot(BeNil()) - }) - }) - - When("interface{} is not a valid type", func() { - It("should return an error", func() { - mw, err := interfaceToMiddleware[string](func() (error, error) { return nil, nil }) - - Expect(err).ToNot(BeNil()) - Expect(mw).To(BeNil()) - }) - }) - }) -}) diff --git a/nitric/options.go b/nitric/options.go index 1b9a537..408ae93 100644 --- a/nitric/options.go +++ b/nitric/options.go @@ -14,10 +14,6 @@ package nitric -import ( - "github.com/nitrictech/go-sdk/nitric/apis" -) - type ( ApiOption = func(api *api) MethodOption = func(mo *methodOptions) @@ -44,16 +40,6 @@ func OidcRule(name string, issuer string, audiences []string) SecurityOption { } } -func WithMiddleware(middleware ...Middleware[apis.Ctx]) ApiOption { - return func(api *api) { - if api.middleware != nil { - api.middleware = ComposeMiddleware(api.middleware, ComposeMiddleware(middleware...)) - } else { - api.middleware = ComposeMiddleware(middleware...) - } - } -} - func WithSecurityJwtRule(name string, rule JwtSecurityRule) ApiOption { return func(api *api) { if api.securityRules == nil { diff --git a/nitric/schedule.go b/nitric/schedule.go index 86300c9..5db42fc 100644 --- a/nitric/schedule.go +++ b/nitric/schedule.go @@ -22,37 +22,25 @@ import ( ) type Schedule interface { - // Run middleware at a certain interval defined by the cronExpression. - // Valid function signatures for middleware are: + // Run a function at a certain interval defined by the cronExpression. + // Valid function signatures for handler are: // // func() // func() error // func(*schedules.Ctx) // func(*schedules.Ctx) error - // func(*schedules.Ctx) *schedules.Ctx - // func(*schedules.Ctx) (*schedules.Ctx, error) - // func(*schedules.Ctx, Handler[schedules.Ctx]) *schedules.Ctx - // func(*schedules.Ctx, Handler[schedules.Ctx]) error - // func(*schedules.Ctx, Handler[schedules.Ctx]) (*schedules.Ctx, error) - // Middleware[schedules.Ctx] // Handler[schedules.Ctx] - Cron(cron string, middleware ...interface{}) + Cron(cron string, handler interface{}) - // Run middleware at a certain interval defined by the rate. The rate is e.g. '7 days'. All rates accept a number and a frequency. Valid frequencies are 'days', 'hours' or 'minutes'. - // Valid function signatures for middleware are: + // Run a function at a certain interval defined by the rate. The rate is e.g. '7 days'. All rates accept a number and a frequency. Valid frequencies are 'days', 'hours' or 'minutes'. + // Valid function signatures for handler are: // // func() // func() error // func(*schedules.Ctx) // func(*schedules.Ctx) error - // func(*schedules.Ctx) *schedules.Ctx - // func(*schedules.Ctx) (*schedules.Ctx, error) - // func(*schedules.Ctx, Handler[schedules.Ctx]) *schedules.Ctx - // func(*schedules.Ctx, Handler[schedules.Ctx]) error - // func(*schedules.Ctx, Handler[schedules.Ctx]) (*schedules.Ctx, error) - // Middleware[schedules.Ctx] // Handler[schedules.Ctx] - Every(rate string, middleware ...interface{}) + Every(rate string, handler interface{}) } type schedule struct { @@ -70,7 +58,7 @@ func NewSchedule(name string) Schedule { } } -func (s *schedule) Cron(cron string, middleware ...interface{}) { +func (s *schedule) Cron(cron string, handler interface{}) { scheduleCron := &schedulespb.ScheduleCron{ Expression: cron, } @@ -82,16 +70,14 @@ func (s *schedule) Cron(cron string, middleware ...interface{}) { }, } - middlewares, err := interfacesToMiddleware[schedules.Ctx](middleware) + typedHandler, err := interfaceToHandler[schedules.Ctx](handler) if err != nil { panic(err) } - composeHandler := ComposeMiddleware(middlewares...) - opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, - Middleware: composeHandler, + Handler: typedHandler, } worker := newScheduleWorker(opts) @@ -101,7 +87,7 @@ func (s *schedule) Cron(cron string, middleware ...interface{}) { }, "-"), worker) } -func (s *schedule) Every(rate string, middleware ...interface{}) { +func (s *schedule) Every(rate string, handler interface{}) { scheduleEvery := &schedulespb.ScheduleEvery{ Rate: rate, } @@ -113,16 +99,14 @@ func (s *schedule) Every(rate string, middleware ...interface{}) { }, } - middlewares, err := interfacesToMiddleware[schedules.Ctx](middleware) + typedHandler, err := interfaceToHandler[schedules.Ctx](handler) if err != nil { panic(err) } - composeHandler := ComposeMiddleware(middlewares...) - opts := &scheduleWorkerOpts{ RegistrationRequest: registrationRequest, - Middleware: composeHandler, + Handler: typedHandler, } worker := newScheduleWorker(opts) diff --git a/nitric/schedule_workers.go b/nitric/schedule_workers.go index e46511f..4ac25c9 100644 --- a/nitric/schedule_workers.go +++ b/nitric/schedule_workers.go @@ -31,11 +31,11 @@ import ( type scheduleWorker struct { client v1.SchedulesClient registrationRequest *v1.RegistrationRequest - middleware Middleware[schedules.Ctx] + handler Handler[schedules.Ctx] } type scheduleWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware Middleware[schedules.Ctx] + Handler Handler[schedules.Ctx] } // Start implements Worker. @@ -69,10 +69,10 @@ func (i *scheduleWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Do nothing + // There is no need to respond to the registration response } else if err == nil && resp.GetIntervalRequest() != nil { ctx = schedules.NewCtx(resp) - ctx, err = i.middleware(ctx, dummyHandler) + err = i.handler(ctx) if err != nil { ctx.WithError(err) } @@ -102,6 +102,6 @@ func newScheduleWorker(opts *scheduleWorkerOpts) *scheduleWorker { return &scheduleWorker{ client: client, registrationRequest: opts.RegistrationRequest, - middleware: opts.Middleware, + handler: opts.Handler, } } diff --git a/nitric/topic.go b/nitric/topic.go index 3d331e5..5dbc3e8 100644 --- a/nitric/topic.go +++ b/nitric/topic.go @@ -36,20 +36,14 @@ type SubscribableTopic interface { Allow(TopicPermission, ...TopicPermission) (*topics.TopicClient, error) // Subscribe will register and start a subscription handler that will be called for all events from this topic. - // Valid function signatures for middleware are: + // Valid function signatures for handler are: // // func() // func() error // func(*topics.Ctx) // func(*topics.Ctx) error - // func(*topics.Ctx) *topics.Ctx - // func(*topics.Ctx) (*topics.Ctx, error) - // func(*topics.Ctx, Handler[topics.Ctx]) *topics.Ctx - // func(*topics.Ctx, Handler[topics.Ctx]) error - // func(*topics.Ctx, Handler[topics.Ctx]) (*topics.Ctx, error) - // Middleware[topics.Ctx] // Handler[topics.Ctx] - Subscribe(...interface{}) + Subscribe(interface{}) } type subscribableTopic struct { @@ -104,21 +98,19 @@ func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...Top return topics.NewTopicClient(t.name) } -func (t *subscribableTopic) Subscribe(middleware ...interface{}) { +func (t *subscribableTopic) Subscribe(handler interface{}) { registrationRequest := &topicspb.RegistrationRequest{ TopicName: t.name, } - middlewares, err := interfacesToMiddleware[topics.Ctx](middleware) + typedHandler, err := interfaceToHandler[topics.Ctx](handler) if err != nil { panic(err) } - composedHandler := ComposeMiddleware(middlewares...) - opts := &subscriptionWorkerOpts{ RegistrationRequest: registrationRequest, - Middleware: composedHandler, + Handler: typedHandler, } worker := newSubscriptionWorker(opts) diff --git a/nitric/topic_workers.go b/nitric/topic_workers.go index 14c10d5..18e5bed 100644 --- a/nitric/topic_workers.go +++ b/nitric/topic_workers.go @@ -32,11 +32,11 @@ import ( type subscriptionWorker struct { client v1.SubscriberClient registrationRequest *v1.RegistrationRequest - middleware Middleware[topics.Ctx] + handler Handler[topics.Ctx] } type subscriptionWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware Middleware[topics.Ctx] + Handler Handler[topics.Ctx] } // Start implements Worker. @@ -70,10 +70,10 @@ func (s *subscriptionWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Do nothing + // There is no need to respond to the registration response } else if err == nil && resp.GetMessageRequest() != nil { ctx = topics.NewCtx(resp) - ctx, err = s.middleware(ctx, dummyHandler) + err = s.handler(ctx) if err != nil { ctx.WithError(err) } @@ -103,6 +103,6 @@ func newSubscriptionWorker(opts *subscriptionWorkerOpts) *subscriptionWorker { return &subscriptionWorker{ client: client, registrationRequest: opts.RegistrationRequest, - middleware: opts.Middleware, + handler: opts.Handler, } } diff --git a/nitric/websocket.go b/nitric/websocket.go index 64b6b86..f77b520 100644 --- a/nitric/websocket.go +++ b/nitric/websocket.go @@ -28,20 +28,14 @@ type Websocket interface { // Name - Get the name of the Websocket API Name() string // On registers a handler for a specific event type on the websocket - // Valid function signatures for middleware are: + // Valid function signatures for handler are: // // func() // func() error // func(*websocket.Ctx) // func(*websocket.Ctx) error - // func(*websocket.Ctx) *websocket.Ctx - // func(*websocket.Ctx) (*websocket.Ctx, error) - // func(*websocket.Ctx, Handler[websocket.Ctx]) *websocket.Ctx - // func(*websocket.Ctx, Handler[websocket.Ctx]) error - // func(*websocket.Ctx, Handler[websocket.Ctx]) (*websocket.Ctx, error) - // Middleware[websocket.Ctx] // Handler[websocket.Ctx] - On(eventType websockets.EventType, mwares ...interface{}) + On(eventType websockets.EventType, handler interface{}) // Send a message to a specific connection Send(ctx context.Context, connectionId string, message []byte) error // Close a specific connection @@ -88,7 +82,7 @@ func (w *websocket) Name() string { return w.name } -func (w *websocket) On(eventType websockets.EventType, middleware ...interface{}) { +func (w *websocket) On(eventType websockets.EventType, handler interface{}) { var _eventType websocketsv1.WebsocketEventType switch eventType { case websockets.EventType_Disconnect: @@ -104,16 +98,14 @@ func (w *websocket) On(eventType websockets.EventType, middleware ...interface{} EventType: _eventType, } - middlewares, err := interfacesToMiddleware[websockets.Ctx](middleware) + typedHandler, err := interfaceToHandler[websockets.Ctx](handler) if err != nil { panic(err) } - composeHandler := ComposeMiddleware(middlewares...) - opts := &websocketWorkerOpts{ RegistrationRequest: registrationRequest, - Middleware: composeHandler, + Handler: typedHandler, } worker := newWebsocketWorker(opts) diff --git a/nitric/websocket_workers.go b/nitric/websocket_workers.go index 6d2bb2a..d23c75a 100644 --- a/nitric/websocket_workers.go +++ b/nitric/websocket_workers.go @@ -31,11 +31,11 @@ import ( type websocketWorker struct { client v1.WebsocketHandlerClient registrationRequest *v1.RegistrationRequest - middleware Middleware[websockets.Ctx] + handler Handler[websockets.Ctx] } type websocketWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Middleware Middleware[websockets.Ctx] + Handler Handler[websockets.Ctx] } // Start implements Worker. @@ -69,10 +69,10 @@ func (w *websocketWorker) Start(ctx context.Context) error { return nil } else if err == nil && resp.GetRegistrationResponse() != nil { - // Do nothing + // There is no need to respond to the registration response } else if err == nil && resp.GetWebsocketEventRequest() != nil { ctx = websockets.NewCtx(resp) - ctx, err = w.middleware(ctx, dummyHandler) + err = w.handler(ctx) if err != nil { ctx.WithError(err) } @@ -102,6 +102,6 @@ func newWebsocketWorker(opts *websocketWorkerOpts) *websocketWorker { return &websocketWorker{ client: client, registrationRequest: opts.RegistrationRequest, - middleware: opts.Middleware, + handler: opts.Handler, } } From eb2d1758eed469a3012d720edb18f83dda3430c3 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 1 Oct 2024 14:07:45 +1000 Subject: [PATCH 26/42] remove unreferenced handler variables --- nitric/api.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/nitric/api.go b/nitric/api.go index 0ac3c9c..48a964c 100644 --- a/nitric/api.go +++ b/nitric/api.go @@ -48,7 +48,6 @@ type Route interface { type route struct { path string api *api - handler Handler[httpx.Ctx] manager *manager } @@ -226,7 +225,6 @@ type api struct { securityRules map[string]interface{} security []OidcOptions path string - handler Handler[httpx.Ctx] } // NewApi Registers a new API Resource. From 39216fd307c56711caba751e525989a3003440cf Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 1 Oct 2024 15:42:40 +1000 Subject: [PATCH 27/42] move resources to their own packages --- nitric/{ => apis}/api.go | 144 ++++++----- nitric/{ => apis}/oidc.go | 15 +- nitric/{ => apis}/options.go | 23 +- nitric/{api_workers.go => apis/workers.go} | 15 +- nitric/bucket.go | 137 ----------- nitric/common.go | 47 ---- nitric/{handler.go => handlers/handlers.go} | 9 +- .../handlers_test.go} | 14 +- nitric/keyvalue/{store.go => client.go} | 0 .../{store_test.go => client_test.go} | 0 nitric/{ => keyvalue}/keyvalue.go | 22 +- nitric/nitric.go | 37 +++ nitric/queue.go | 91 ------- nitric/queues/client.go | 126 ++++++++++ .../queues/{queue_test.go => client_test.go} | 0 nitric/queues/queue.go | 135 ++++------- nitric/resource/resource.go | 24 ++ nitric/{ => schedules}/schedule.go | 17 +- nitric/{ => schedules}/schedule_workers.go | 12 +- nitric/secrets/{secrets.go => client.go} | 0 .../{secrets_test.go => client_test.go} | 0 nitric/{ => secrets}/secret.go | 20 +- nitric/sql.go | 59 ----- nitric/sql/client.go | 72 ++++++ nitric/sql/sql.go | 79 +++--- nitric/storage/bucket.go | 228 +++++++----------- nitric/{ => storage}/bucket_workers.go | 12 +- nitric/storage/client.go | 192 +++++++++++++++ .../{bucket_test.go => client_test.go} | 0 nitric/topic.go | 118 --------- nitric/topics/client.go | 102 ++++++++ .../topics/{topic_test.go => client_test.go} | 0 nitric/topics/topic.go | 134 +++++----- nitric/{ => topics}/topic_workers.go | 12 +- nitric/{ => websockets}/websocket.go | 34 ++- nitric/{ => websockets}/websocket_workers.go | 12 +- nitric/{ => workers}/manager.go | 59 ++++- nitric/{ => workers}/workers.go | 4 +- 38 files changed, 1038 insertions(+), 967 deletions(-) rename nitric/{ => apis}/api.go (89%) rename nitric/{ => apis}/oidc.go (79%) rename nitric/{ => apis}/options.go (69%) rename nitric/{api_workers.go => apis/workers.go} (89%) delete mode 100644 nitric/bucket.go delete mode 100644 nitric/common.go rename nitric/{handler.go => handlers/handlers.go} (84%) rename nitric/{handler_test.go => handlers/handlers_test.go} (79%) rename nitric/keyvalue/{store.go => client.go} (100%) rename nitric/keyvalue/{store_test.go => client_test.go} (100%) rename nitric/{ => keyvalue}/keyvalue.go (79%) create mode 100644 nitric/nitric.go delete mode 100644 nitric/queue.go create mode 100644 nitric/queues/client.go rename nitric/queues/{queue_test.go => client_test.go} (100%) create mode 100644 nitric/resource/resource.go rename nitric/{ => schedules}/schedule.go (85%) rename nitric/{ => schedules}/schedule_workers.go (92%) rename nitric/secrets/{secrets.go => client.go} (100%) rename nitric/secrets/{secrets_test.go => client_test.go} (100%) rename nitric/{ => secrets}/secret.go (81%) delete mode 100644 nitric/sql.go create mode 100644 nitric/sql/client.go rename nitric/{ => storage}/bucket_workers.go (92%) create mode 100644 nitric/storage/client.go rename nitric/storage/{bucket_test.go => client_test.go} (100%) delete mode 100644 nitric/topic.go create mode 100644 nitric/topics/client.go rename nitric/topics/{topic_test.go => client_test.go} (100%) rename nitric/{ => topics}/topic_workers.go (92%) rename nitric/{ => websockets}/websocket.go (79%) rename nitric/{ => websockets}/websocket_workers.go (92%) rename nitric/{ => workers}/manager.go (73%) rename nitric/{ => workers}/workers.go (93%) diff --git a/nitric/api.go b/nitric/apis/api.go similarity index 89% rename from nitric/api.go rename to nitric/apis/api.go index 48a964c..b47e149 100644 --- a/nitric/api.go +++ b/nitric/apis/api.go @@ -12,17 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package apis import ( "net/http" "path" "strings" - httpx "github.com/nitrictech/go-sdk/nitric/apis" + . "github.com/nitrictech/go-sdk/nitric/handlers" + resources "github.com/nitrictech/go-sdk/nitric/resource" + "github.com/nitrictech/go-sdk/nitric/workers" + resourcev1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" - resourcev1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) // Route providers convenience functions to register a handler in a single method. @@ -45,13 +47,16 @@ type Route interface { ApiName() string } +type ApiMiddleware = Middleware[Ctx] + type route struct { - path string - api *api - manager *manager + path string + api *api + manager *workers.Manager + middleware ApiMiddleware } -func (a *api) NewRoute(match string) Route { +func (a *api) NewRoute(match string, opts ...RouteOption) Route { r, ok := a.routes[match] if !ok { r = &route{ @@ -61,6 +66,10 @@ func (a *api) NewRoute(match string) Route { } } + for _, o := range opts { + o(r.(*route)) + } + return r } @@ -81,7 +90,7 @@ func (r *route) AddMethodHandler(methods []string, handler interface{}, opts ... o(mo) } - typedHandler, err := interfaceToHandler[httpx.Ctx](handler) + typedHandler, err := HandlerFromInterface[Ctx](handler) if err != nil { panic(err) } @@ -93,7 +102,7 @@ func (r *route) AddMethodHandler(methods []string, handler interface{}, opts ... if mo.security != nil && !mo.securityDisabled { for _, oidcOption := range mo.security { - err := attachOidc(r.api.name, oidcOption) + err := attachOidc(r.api.name, oidcOption, r.manager) if err != nil { return err } @@ -111,12 +120,20 @@ func (r *route) AddMethodHandler(methods []string, handler interface{}, opts ... Options: apiOpts, } + if r.middleware != nil { + typedHandler = r.middleware(typedHandler) + } + + if r.api.middleware != nil { + typedHandler = r.api.middleware(typedHandler) + } + wkr := newApiWorker(&apiWorkerOpts{ RegistrationRequest: registrationRequest, Handler: typedHandler, }) - r.manager.addWorker("route:"+bName, wkr) + r.manager.AddWorker("route:"+bName, wkr) return nil } @@ -210,71 +227,22 @@ type Api interface { // Handler[apis.Ctx] Options(path string, handler interface{}, opts ...MethodOption) // NewRoute creates a new Route object for the given path. - NewRoute(path string) Route + NewRoute(path string, opts ...RouteOption) Route } type ApiDetails struct { - Details + resources.Details URL string } type api struct { name string routes map[string]Route - manager *manager + manager *workers.Manager securityRules map[string]interface{} security []OidcOptions path string -} - -// NewApi Registers a new API Resource. -// -// The returned API object can be used to register Routes and Methods, with Handlers. -func NewApi(name string, opts ...ApiOption) (Api, error) { - a := &api{ - name: name, - routes: map[string]Route{}, - manager: defaultManager, - } - - // Apply options - for _, o := range opts { - o(a) - } - - apiResource := &resourcev1.ApiResource{} - - // Attaching OIDC Options to API - if a.security != nil { - for _, oidcOption := range a.security { - err := attachOidc(a.name, oidcOption) - if err != nil { - return nil, err - } - - if apiResource.GetSecurity() == nil { - apiResource.Security = make(map[string]*resourcev1.ApiScopes) - } - apiResource.Security[oidcOption.Name] = &resourcev1.ApiScopes{ - Scopes: oidcOption.Scopes, - } - } - } - // declare resource - result := <-defaultManager.registerResource(&resourcev1.ResourceDeclareRequest{ - Id: &resourcev1.ResourceIdentifier{ - Name: name, - Type: resourcev1.ResourceType_Api, - }, - Config: &resourcev1.ResourceDeclareRequest_Api{ - Api: apiResource, - }, - }) - if result.Err != nil { - return nil, result.Err - } - - return a, nil + middleware ApiMiddleware } // Get adds a Get method handler to the path with any specified opts. @@ -330,3 +298,53 @@ func (a *api) Options(match string, handler interface{}, opts ...MethodOption) { r.Options(handler, opts...) a.routes[match] = r } + +// NewApi Registers a new API Resource. +// +// The returned API object can be used to register Routes and Methods, with Handlers. +func NewApi(name string, opts ...ApiOption) (Api, error) { + a := &api{ + name: name, + routes: map[string]Route{}, + manager: workers.GetDefaultManager(), + } + + // Apply options + for _, o := range opts { + o(a) + } + + apiResource := &resourcev1.ApiResource{} + + // Attaching OIDC Options to API + if a.security != nil { + for _, oidcOption := range a.security { + err := attachOidc(a.name, oidcOption, a.manager) + if err != nil { + return nil, err + } + + if apiResource.GetSecurity() == nil { + apiResource.Security = make(map[string]*resourcev1.ApiScopes) + } + apiResource.Security[oidcOption.Name] = &resourcev1.ApiScopes{ + Scopes: oidcOption.Scopes, + } + } + } + // declare resource + result := <-a.manager.RegisterResource(&resourcev1.ResourceDeclareRequest{ + Id: &resourcev1.ResourceIdentifier{ + Name: name, + Type: resourcev1.ResourceType_Api, + }, + Config: &resourcev1.ResourceDeclareRequest_Api{ + Api: apiResource, + }, + }) + if result.Err != nil { + return nil, result.Err + } + + return a, nil +} diff --git a/nitric/oidc.go b/nitric/apis/oidc.go similarity index 79% rename from nitric/oidc.go rename to nitric/apis/oidc.go index 7073dbb..1065567 100644 --- a/nitric/oidc.go +++ b/nitric/apis/oidc.go @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package apis import ( + "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) @@ -25,8 +26,8 @@ type OidcOptions struct { Scopes []string } -func attachOidc(apiName string, options OidcOptions) error { - _, err := NewOidcSecurityDefinition(apiName, options) +func attachOidc(apiName string, options OidcOptions, manager *workers.Manager) error { + _, err := newOidcSecurityDefinition(apiName, options, manager) if err != nil { return err } @@ -45,20 +46,20 @@ type oidcSecurityDefinition struct { Issuer string Audiences []string - manager *manager + manager *workers.Manager } -func NewOidcSecurityDefinition(apiName string, options OidcOptions) (OidcSecurityDefinition, error) { +func newOidcSecurityDefinition(apiName string, options OidcOptions, manager *workers.Manager) (OidcSecurityDefinition, error) { o := &oidcSecurityDefinition{ ApiName: apiName, RuleName: options.Name, Issuer: options.Issuer, Audiences: options.Audiences, - manager: defaultManager, + manager: manager, } // declare resource - registerResult := <-defaultManager.registerResource(&v1.ResourceDeclareRequest{ + registerResult := <-manager.RegisterResource(&v1.ResourceDeclareRequest{ Id: &v1.ResourceIdentifier{ Name: options.Name, Type: v1.ResourceType_ApiSecurityDefinition, diff --git a/nitric/options.go b/nitric/apis/options.go similarity index 69% rename from nitric/options.go rename to nitric/apis/options.go index 408ae93..27abb57 100644 --- a/nitric/options.go +++ b/nitric/apis/options.go @@ -1,21 +1,8 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric +package apis type ( ApiOption = func(api *api) + RouteOption = func(route Route) MethodOption = func(mo *methodOptions) ) @@ -29,6 +16,12 @@ type methodOptions struct { securityDisabled bool } +func WithMiddleware(middleware ApiMiddleware) ApiOption { + return func(api *api) { + api.middleware = middleware + } +} + func OidcRule(name string, issuer string, audiences []string) SecurityOption { return func(scopes []string) OidcOptions { return OidcOptions{ diff --git a/nitric/api_workers.go b/nitric/apis/workers.go similarity index 89% rename from nitric/api_workers.go rename to nitric/apis/workers.go index ace8f0b..bddec64 100644 --- a/nitric/api_workers.go +++ b/nitric/apis/workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package apis import ( "context" @@ -22,24 +22,25 @@ import ( "google.golang.org/grpc" "github.com/nitrictech/go-sdk/constants" - httpx "github.com/nitrictech/go-sdk/nitric/apis" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" + "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" ) type apiWorker struct { client v1.ApiClient - Handler Handler[httpx.Ctx] + Handler handlers.Handler[Ctx] registrationRequest *v1.RegistrationRequest } type apiWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Handler Handler[httpx.Ctx] + Handler handlers.Handler[Ctx] } -var _ streamWorker = (*apiWorker)(nil) +var _ workers.StreamWorker = (*apiWorker)(nil) // Start implements Worker. func (a *apiWorker) Start(ctx context.Context) error { @@ -60,7 +61,7 @@ func (a *apiWorker) Start(ctx context.Context) error { } for { - var ctx *httpx.Ctx + var ctx *Ctx resp, err := stream.Recv() @@ -74,7 +75,7 @@ func (a *apiWorker) Start(ctx context.Context) error { } else if err == nil && resp.GetRegistrationResponse() != nil { // There is no need to respond to the registration response } else if err == nil && resp.GetHttpRequest() != nil { - ctx = httpx.NewCtx(resp) + ctx = NewCtx(resp) err = a.Handler(ctx) if err != nil { diff --git a/nitric/bucket.go b/nitric/bucket.go deleted file mode 100644 index 5ae3b75..0000000 --- a/nitric/bucket.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -import ( - "fmt" - "strings" - - "github.com/nitrictech/go-sdk/nitric/storage" - v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" - storagepb "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" -) - -type BucketPermission string - -type bucket struct { - name string - manager *manager - registerChan <-chan RegisterResult -} - -type Bucket interface { - // Allow requests the given permissions to the bucket. - Allow(BucketPermission, ...BucketPermission) (*storage.BucketClient, error) - - // On registers a handler for a specific event type on the bucket. - // Valid function signatures for handler are: - // - // func() - // func() error - // func(*storage.Ctx) - // func(*storage.Ctx) error - // Handler[storage.Ctx] - On(eventType storage.EventType, notificationPrefixFilter string, handler interface{}) -} - -const ( - BucketRead BucketPermission = "read" - BucketWrite BucketPermission = "write" - BucketDelete BucketPermission = "delete" -) - -var BucketEverything []BucketPermission = []BucketPermission{BucketRead, BucketWrite, BucketDelete} - -// NewBucket - Create a new Bucket resource -func NewBucket(name string) Bucket { - bucket := &bucket{ - name: name, - manager: defaultManager, - } - - bucket.registerChan = defaultManager.registerResource(&v1.ResourceDeclareRequest{ - Id: &v1.ResourceIdentifier{ - Type: v1.ResourceType_Bucket, - Name: name, - }, - Config: &v1.ResourceDeclareRequest_Bucket{ - Bucket: &v1.BucketResource{}, - }, - }) - - return bucket -} - -func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) (*storage.BucketClient, error) { - allPerms := append([]BucketPermission{permission}, permissions...) - - actions := []v1.Action{} - for _, perm := range allPerms { - switch perm { - case BucketRead: - actions = append(actions, v1.Action_BucketFileGet, v1.Action_BucketFileList) - case BucketWrite: - actions = append(actions, v1.Action_BucketFilePut) - case BucketDelete: - actions = append(actions, v1.Action_BucketFileDelete) - default: - return nil, fmt.Errorf("bucketPermission %s unknown", perm) - } - } - - registerResult := <-b.registerChan - if registerResult.Err != nil { - return nil, registerResult.Err - } - - err := b.manager.registerPolicy(registerResult.Identifier, actions...) - if err != nil { - return nil, err - } - - return storage.NewBucketClient(b.name) -} - -func (b *bucket) On(eventType storage.EventType, notificationPrefixFilter string, handler interface{}) { - var blobEventType storagepb.BlobEventType - switch eventType { - case storage.WriteNotification: - blobEventType = storagepb.BlobEventType_Created - case storage.DeleteNotification: - blobEventType = storagepb.BlobEventType_Deleted - } - - registrationRequest := &storagepb.RegistrationRequest{ - BucketName: b.name, - BlobEventType: blobEventType, - KeyPrefixFilter: notificationPrefixFilter, - } - - typedHandler, err := interfaceToHandler[storage.Ctx](handler) - if err != nil { - panic(err) - } - - opts := &bucketEventWorkerOpts{ - RegistrationRequest: registrationRequest, - Handler: typedHandler, - } - - worker := newBucketEventWorker(opts) - - b.manager.addWorker("bucketNotification:"+strings.Join([]string{ - b.name, notificationPrefixFilter, string(eventType), - }, "-"), worker) -} diff --git a/nitric/common.go b/nitric/common.go deleted file mode 100644 index 4b95940..0000000 --- a/nitric/common.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -import ( - nitricv1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" -) - -func functionResourceDeclareRequest(subject *nitricv1.ResourceIdentifier, actions []nitricv1.Action) *nitricv1.ResourceDeclareRequest { - return &nitricv1.ResourceDeclareRequest{ - Id: &nitricv1.ResourceIdentifier{ - Type: nitricv1.ResourceType_Policy, - }, - Config: &nitricv1.ResourceDeclareRequest_Policy{ - Policy: &nitricv1.PolicyResource{ - Principals: []*nitricv1.ResourceIdentifier{ - { - Type: nitricv1.ResourceType_Service, - }, - }, - Actions: actions, - Resources: []*nitricv1.ResourceIdentifier{subject}, - }, - }, - } -} - -type Details struct { - // The identifier of the resource - ID string - // The provider this resource is deployed with (e.g. aws) - Provider string - // The service this resource is deployed on (e.g. ApiGateway) - Service string -} diff --git a/nitric/handler.go b/nitric/handlers/handlers.go similarity index 84% rename from nitric/handler.go rename to nitric/handlers/handlers.go index 2deaea4..13d2a25 100644 --- a/nitric/handler.go +++ b/nitric/handlers/handlers.go @@ -12,15 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package handlers import "fmt" type ( - Handler[T any] func(context *T) error + Handler[T any] func(context *T) error + Middleware[T any] func(Handler[T]) Handler[T] ) -// interfaceToHandler - Converts a function to a Handler +// fromInterface - Converts a function to a Handler // Valid function types are: // func() // func() error @@ -30,7 +31,7 @@ type ( // func(*T) (*T, error) // Handler[T] // If the function is not a valid type, an error is returned -func interfaceToHandler[T any](handler interface{}) (Handler[T], error) { +func HandlerFromInterface[T any](handler interface{}) (Handler[T], error) { var typedHandler Handler[T] switch handlerType := handler.(type) { case func(): diff --git a/nitric/handler_test.go b/nitric/handlers/handlers_test.go similarity index 79% rename from nitric/handler_test.go rename to nitric/handlers/handlers_test.go index 2432341..e9cd53f 100644 --- a/nitric/handler_test.go +++ b/nitric/handlers/handlers_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package handlers import ( . "github.com/onsi/ginkgo" @@ -26,10 +26,10 @@ var _ = Describe("handler", func() { // func(*T) error // func(*T, Handler[T]) error // Handler[T] - Context("interfaceToHandler", func() { + Context("HandlerFromInterface", func() { When("interface{} is func()", func() { It("should return a valid handler", func() { - handler, err := interfaceToHandler[any](func() {}) + handler, err := HandlerFromInterface[any](func() {}) Expect(err).To(BeNil()) Expect(handler).ToNot(BeNil()) @@ -38,7 +38,7 @@ var _ = Describe("handler", func() { When("interface{} is func() error", func() { It("should return a valid handler", func() { - handler, err := interfaceToHandler[any](func() error { return nil }) + handler, err := HandlerFromInterface[any](func() error { return nil }) Expect(err).To(BeNil()) Expect(handler).ToNot(BeNil()) @@ -47,7 +47,7 @@ var _ = Describe("handler", func() { When("interface{} is func(*T)", func() { It("should return a valid handler", func() { - handler, err := interfaceToHandler[string](func(*string) {}) + handler, err := HandlerFromInterface[string](func(*string) {}) Expect(err).To(BeNil()) Expect(handler).ToNot(BeNil()) @@ -56,7 +56,7 @@ var _ = Describe("handler", func() { When("interface{} is func(*T) error", func() { It("should return a valid handler", func() { - handler, err := interfaceToHandler[string](func(*string) error { return nil }) + handler, err := HandlerFromInterface[string](func(*string) error { return nil }) Expect(err).To(BeNil()) Expect(handler).ToNot(BeNil()) @@ -65,7 +65,7 @@ var _ = Describe("handler", func() { When("interface{} is not a valid type", func() { It("should return an error", func() { - handler, err := interfaceToHandler[string](func() (error, error) { return nil, nil }) + handler, err := HandlerFromInterface[string](func() (error, error) { return nil, nil }) Expect(err).ToNot(BeNil()) Expect(handler).To(BeNil()) diff --git a/nitric/keyvalue/store.go b/nitric/keyvalue/client.go similarity index 100% rename from nitric/keyvalue/store.go rename to nitric/keyvalue/client.go diff --git a/nitric/keyvalue/store_test.go b/nitric/keyvalue/client_test.go similarity index 100% rename from nitric/keyvalue/store_test.go rename to nitric/keyvalue/client_test.go diff --git a/nitric/keyvalue.go b/nitric/keyvalue/keyvalue.go similarity index 79% rename from nitric/keyvalue.go rename to nitric/keyvalue/keyvalue.go index 885318c..3ed5f0c 100644 --- a/nitric/keyvalue.go +++ b/nitric/keyvalue/keyvalue.go @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package keyvalue import ( "fmt" - "github.com/nitrictech/go-sdk/nitric/keyvalue" + "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) @@ -33,24 +33,24 @@ var KvStoreEverything []KvStorePermission = []KvStorePermission{KvStoreSet, KvSt type KvStore interface { // Allow requests the given permissions to the key/value store. - Allow(KvStorePermission, ...KvStorePermission) (keyvalue.KvStoreClientIface, error) + Allow(KvStorePermission, ...KvStorePermission) (KvStoreClientIface, error) } type kvstore struct { name string - manager *manager - registerChan <-chan RegisterResult + manager *workers.Manager + registerChan <-chan workers.RegisterResult } // NewKv - Create a new Key/Value store resource func NewKv(name string) *kvstore { kvstore := &kvstore{ name: name, - manager: defaultManager, - registerChan: make(chan RegisterResult), + manager: workers.GetDefaultManager(), + registerChan: make(chan workers.RegisterResult), } - kvstore.registerChan = defaultManager.registerResource(&v1.ResourceDeclareRequest{ + kvstore.registerChan = kvstore.manager.RegisterResource(&v1.ResourceDeclareRequest{ Id: &v1.ResourceIdentifier{ Type: v1.ResourceType_KeyValueStore, Name: name, @@ -63,7 +63,7 @@ func NewKv(name string) *kvstore { return kvstore } -func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePermission) (keyvalue.KvStoreClientIface, error) { +func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePermission) (KvStoreClientIface, error) { allPerms := append([]KvStorePermission{permission}, permissions...) actions := []v1.Action{} @@ -86,10 +86,10 @@ func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePerm return nil, registerResult.Err } - err := k.manager.registerPolicy(registerResult.Identifier, actions...) + err := k.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - return keyvalue.NewKvStoreClient(k.name) + return NewKvStoreClient(k.name) } diff --git a/nitric/nitric.go b/nitric/nitric.go new file mode 100644 index 0000000..0a44b11 --- /dev/null +++ b/nitric/nitric.go @@ -0,0 +1,37 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 nitric + +import ( + "github.com/nitrictech/go-sdk/nitric/apis" + "github.com/nitrictech/go-sdk/nitric/keyvalue" + "github.com/nitrictech/go-sdk/nitric/queues" + "github.com/nitrictech/go-sdk/nitric/schedules" + "github.com/nitrictech/go-sdk/nitric/secrets" + "github.com/nitrictech/go-sdk/nitric/sql" + "github.com/nitrictech/go-sdk/nitric/storage" + "github.com/nitrictech/go-sdk/nitric/topics" + "github.com/nitrictech/go-sdk/nitric/websockets" +) + +var NewApi = apis.NewApi +var NewKv = keyvalue.NewKv +var NewQueue = queues.NewQueue +var NewSchedule = schedules.NewSchedule +var NewSecret = secrets.NewSecret +var NewSqlDatabase = sql.NewSqlDatabase +var NewBucket = storage.NewBucket +var NewTopic = topics.NewTopic +var NewWebsocket = websockets.NewWebsocket diff --git a/nitric/queue.go b/nitric/queue.go deleted file mode 100644 index c393d20..0000000 --- a/nitric/queue.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -import ( - "fmt" - - "github.com/nitrictech/go-sdk/nitric/queues" - v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" -) - -type QueuePermission string - -const ( - QueueEnqueue QueuePermission = "enqueue" - QueueDequeue QueuePermission = "dequeue" -) - -var QueueEverything []QueuePermission = []QueuePermission{QueueEnqueue, QueueDequeue} - -type Queue interface { - // Allow requests the given permissions to the queue. - Allow(QueuePermission, ...QueuePermission) (*queues.QueueClient, error) -} - -type queue struct { - name string - manager *manager - registerChan <-chan RegisterResult -} - -// NewQueue - Create a new Queue resource -func NewQueue(name string) *queue { - queue := &queue{ - name: name, - manager: defaultManager, - registerChan: make(chan RegisterResult), - } - - queue.registerChan = defaultManager.registerResource(&v1.ResourceDeclareRequest{ - Id: &v1.ResourceIdentifier{ - Type: v1.ResourceType_Queue, - Name: name, - }, - Config: &v1.ResourceDeclareRequest_Queue{ - Queue: &v1.QueueResource{}, - }, - }) - - return queue -} - -func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission) (*queues.QueueClient, error) { - allPerms := append([]QueuePermission{permission}, permissions...) - - actions := []v1.Action{} - for _, perm := range allPerms { - switch perm { - case QueueDequeue: - actions = append(actions, v1.Action_QueueDequeue) - case QueueEnqueue: - actions = append(actions, v1.Action_QueueEnqueue) - default: - return nil, fmt.Errorf("QueuePermission %s unknown", perm) - } - } - - registerResult := <-q.registerChan - if registerResult.Err != nil { - return nil, registerResult.Err - } - - err := q.manager.registerPolicy(registerResult.Identifier, actions...) - if err != nil { - return nil, err - } - - return queues.NewQueueClient(q.name) -} diff --git a/nitric/queues/client.go b/nitric/queues/client.go new file mode 100644 index 0000000..93a24de --- /dev/null +++ b/nitric/queues/client.go @@ -0,0 +1,126 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 queues + +import ( + "context" + + "google.golang.org/grpc" + + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + v1 "github.com/nitrictech/nitric/core/pkg/proto/queues/v1" +) + +// QueueClientIface is a resource for async enqueueing/dequeueing of messages. +type QueueClientIface interface { + // Name - The name of the queue + Name() string + // Enqueue - Push a number of messages to a queue + Enqueue(context.Context, []map[string]interface{}) ([]*FailedMessage, error) + // Dequeue - Retrieve messages from a queue to a maximum of the given depth + Dequeue(context.Context, int) ([]ReceivedMessage, error) +} + +type QueueClient struct { + name string + queueClient v1.QueuesClient +} + +func (q *QueueClient) Name() string { + return q.name +} + +func (q *QueueClient) Dequeue(ctx context.Context, depth int) ([]ReceivedMessage, error) { + if depth < 1 { + return nil, errors.New(codes.InvalidArgument, "Queue.Dequeue: depth cannot be less than 1") + } + + r, err := q.queueClient.Dequeue(ctx, &v1.QueueDequeueRequest{ + QueueName: q.name, + Depth: int32(depth), + }) + if err != nil { + return nil, errors.FromGrpcError(err) + } + + rts := make([]ReceivedMessage, len(r.GetMessages())) + + for i, message := range r.GetMessages() { + rts[i] = &leasedMessage{ + queueName: q.name, + queueClient: q.queueClient, + leaseId: message.GetLeaseId(), + message: wireToMessage(message.GetMessage()), + } + } + + return rts, nil +} + +func (q *QueueClient) Enqueue(ctx context.Context, messages []map[string]interface{}) ([]*FailedMessage, error) { + // Convert SDK Message objects to gRPC Message objects + wireMessages := make([]*v1.QueueMessage, len(messages)) + for i, message := range messages { + wireMessage, err := messageToWire(message) + if err != nil { + return nil, errors.NewWithCause( + codes.Internal, + "Queue.Enqueue: Unable to enqueue messages", + err, + ) + } + wireMessages[i] = wireMessage + } + + // Push the messages to the queue + res, err := q.queueClient.Enqueue(ctx, &v1.QueueEnqueueRequest{ + QueueName: q.name, + Messages: wireMessages, + }) + if err != nil { + return nil, errors.FromGrpcError(err) + } + + // Convert the gRPC Failed Messages to SDK Failed Message objects + failedMessages := make([]*FailedMessage, len(res.GetFailedMessages())) + for i, failedMessage := range res.GetFailedMessages() { + failedMessages[i] = &FailedMessage{ + Message: wireToMessage(failedMessage.GetMessage()), + Reason: failedMessage.GetDetails(), + } + } + + return failedMessages, nil +} + +func NewQueueClient(name string) (*QueueClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "NewQueueClient: unable to reach nitric server", + err, + ) + } + + queueClient := v1.NewQueuesClient(conn) + + return &QueueClient{ + name: name, + queueClient: queueClient, + }, nil +} diff --git a/nitric/queues/queue_test.go b/nitric/queues/client_test.go similarity index 100% rename from nitric/queues/queue_test.go rename to nitric/queues/client_test.go diff --git a/nitric/queues/queue.go b/nitric/queues/queue.go index 93a24de..d380b95 100644 --- a/nitric/queues/queue.go +++ b/nitric/queues/queue.go @@ -15,112 +15,77 @@ package queues import ( - "context" + "fmt" - "google.golang.org/grpc" + "github.com/nitrictech/go-sdk/nitric/workers" + v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" +) + +type QueuePermission string - "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/nitric/errors" - "github.com/nitrictech/go-sdk/nitric/errors/codes" - v1 "github.com/nitrictech/nitric/core/pkg/proto/queues/v1" +const ( + QueueEnqueue QueuePermission = "enqueue" + QueueDequeue QueuePermission = "dequeue" ) -// QueueClientIface is a resource for async enqueueing/dequeueing of messages. -type QueueClientIface interface { - // Name - The name of the queue - Name() string - // Enqueue - Push a number of messages to a queue - Enqueue(context.Context, []map[string]interface{}) ([]*FailedMessage, error) - // Dequeue - Retrieve messages from a queue to a maximum of the given depth - Dequeue(context.Context, int) ([]ReceivedMessage, error) -} +var QueueEverything []QueuePermission = []QueuePermission{QueueEnqueue, QueueDequeue} -type QueueClient struct { - name string - queueClient v1.QueuesClient +type Queue interface { + // Allow requests the given permissions to the queue. + Allow(QueuePermission, ...QueuePermission) (*QueueClient, error) } -func (q *QueueClient) Name() string { - return q.name +type queue struct { + name string + manager *workers.Manager + registerChan <-chan workers.RegisterResult } -func (q *QueueClient) Dequeue(ctx context.Context, depth int) ([]ReceivedMessage, error) { - if depth < 1 { - return nil, errors.New(codes.InvalidArgument, "Queue.Dequeue: depth cannot be less than 1") +// NewQueue - Create a new Queue resource +func NewQueue(name string) *queue { + queue := &queue{ + name: name, + manager: workers.GetDefaultManager(), + registerChan: make(chan workers.RegisterResult), } - r, err := q.queueClient.Dequeue(ctx, &v1.QueueDequeueRequest{ - QueueName: q.name, - Depth: int32(depth), + queue.registerChan = queue.manager.RegisterResource(&v1.ResourceDeclareRequest{ + Id: &v1.ResourceIdentifier{ + Type: v1.ResourceType_Queue, + Name: name, + }, + Config: &v1.ResourceDeclareRequest_Queue{ + Queue: &v1.QueueResource{}, + }, }) - if err != nil { - return nil, errors.FromGrpcError(err) - } - - rts := make([]ReceivedMessage, len(r.GetMessages())) - - for i, message := range r.GetMessages() { - rts[i] = &leasedMessage{ - queueName: q.name, - queueClient: q.queueClient, - leaseId: message.GetLeaseId(), - message: wireToMessage(message.GetMessage()), - } - } - return rts, nil + return queue } -func (q *QueueClient) Enqueue(ctx context.Context, messages []map[string]interface{}) ([]*FailedMessage, error) { - // Convert SDK Message objects to gRPC Message objects - wireMessages := make([]*v1.QueueMessage, len(messages)) - for i, message := range messages { - wireMessage, err := messageToWire(message) - if err != nil { - return nil, errors.NewWithCause( - codes.Internal, - "Queue.Enqueue: Unable to enqueue messages", - err, - ) +func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission) (*QueueClient, error) { + allPerms := append([]QueuePermission{permission}, permissions...) + + actions := []v1.Action{} + for _, perm := range allPerms { + switch perm { + case QueueDequeue: + actions = append(actions, v1.Action_QueueDequeue) + case QueueEnqueue: + actions = append(actions, v1.Action_QueueEnqueue) + default: + return nil, fmt.Errorf("QueuePermission %s unknown", perm) } - wireMessages[i] = wireMessage } - // Push the messages to the queue - res, err := q.queueClient.Enqueue(ctx, &v1.QueueEnqueueRequest{ - QueueName: q.name, - Messages: wireMessages, - }) - if err != nil { - return nil, errors.FromGrpcError(err) - } - - // Convert the gRPC Failed Messages to SDK Failed Message objects - failedMessages := make([]*FailedMessage, len(res.GetFailedMessages())) - for i, failedMessage := range res.GetFailedMessages() { - failedMessages[i] = &FailedMessage{ - Message: wireToMessage(failedMessage.GetMessage()), - Reason: failedMessage.GetDetails(), - } + registerResult := <-q.registerChan + if registerResult.Err != nil { + return nil, registerResult.Err } - return failedMessages, nil -} - -func NewQueueClient(name string) (*QueueClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + err := q.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "NewQueueClient: unable to reach nitric server", - err, - ) + return nil, err } - queueClient := v1.NewQueuesClient(conn) - - return &QueueClient{ - name: name, - queueClient: queueClient, - }, nil + return NewQueueClient(q.name) } diff --git a/nitric/resource/resource.go b/nitric/resource/resource.go new file mode 100644 index 0000000..0b30e25 --- /dev/null +++ b/nitric/resource/resource.go @@ -0,0 +1,24 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 resources + +type Details struct { + // The identifier of the resource + ID string + // The provider this resource is deployed with (e.g. aws) + Provider string + // The service this resource is deployed on (e.g. ApiGateway) + Service string +} diff --git a/nitric/schedule.go b/nitric/schedules/schedule.go similarity index 85% rename from nitric/schedule.go rename to nitric/schedules/schedule.go index 5db42fc..586bd0d 100644 --- a/nitric/schedule.go +++ b/nitric/schedules/schedule.go @@ -12,12 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package schedules import ( "strings" - "github.com/nitrictech/go-sdk/nitric/schedules" + "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/nitric/workers" schedulespb "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) @@ -45,7 +46,7 @@ type Schedule interface { type schedule struct { name string - manager *manager + manager *workers.Manager } var _ Schedule = (*schedule)(nil) @@ -54,7 +55,7 @@ var _ Schedule = (*schedule)(nil) func NewSchedule(name string) Schedule { return &schedule{ name: name, - manager: defaultManager, + manager: workers.GetDefaultManager(), } } @@ -70,7 +71,7 @@ func (s *schedule) Cron(cron string, handler interface{}) { }, } - typedHandler, err := interfaceToHandler[schedules.Ctx](handler) + typedHandler, err := handlers.HandlerFromInterface[Ctx](handler) if err != nil { panic(err) } @@ -81,7 +82,7 @@ func (s *schedule) Cron(cron string, handler interface{}) { } worker := newScheduleWorker(opts) - s.manager.addWorker("IntervalWorkerCron:"+strings.Join([]string{ + s.manager.AddWorker("IntervalWorkerCron:"+strings.Join([]string{ s.name, cron, }, "-"), worker) @@ -99,7 +100,7 @@ func (s *schedule) Every(rate string, handler interface{}) { }, } - typedHandler, err := interfaceToHandler[schedules.Ctx](handler) + typedHandler, err := handlers.HandlerFromInterface[Ctx](handler) if err != nil { panic(err) } @@ -110,7 +111,7 @@ func (s *schedule) Every(rate string, handler interface{}) { } worker := newScheduleWorker(opts) - s.manager.addWorker("IntervalWorkerEvery:"+strings.Join([]string{ + s.manager.AddWorker("IntervalWorkerEvery:"+strings.Join([]string{ s.name, rate, }, "-"), worker) diff --git a/nitric/schedule_workers.go b/nitric/schedules/schedule_workers.go similarity index 92% rename from nitric/schedule_workers.go rename to nitric/schedules/schedule_workers.go index 4ac25c9..0dc1399 100644 --- a/nitric/schedule_workers.go +++ b/nitric/schedules/schedule_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package schedules import ( "context" @@ -24,18 +24,18 @@ import ( "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/schedules" + "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) type scheduleWorker struct { client v1.SchedulesClient registrationRequest *v1.RegistrationRequest - handler Handler[schedules.Ctx] + handler handlers.Handler[Ctx] } type scheduleWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Handler Handler[schedules.Ctx] + Handler handlers.Handler[Ctx] } // Start implements Worker. @@ -57,7 +57,7 @@ func (i *scheduleWorker) Start(ctx context.Context) error { return err } for { - var ctx *schedules.Ctx + var ctx *Ctx resp, err := stream.Recv() @@ -71,7 +71,7 @@ func (i *scheduleWorker) Start(ctx context.Context) error { } else if err == nil && resp.GetRegistrationResponse() != nil { // There is no need to respond to the registration response } else if err == nil && resp.GetIntervalRequest() != nil { - ctx = schedules.NewCtx(resp) + ctx = NewCtx(resp) err = i.handler(ctx) if err != nil { ctx.WithError(err) diff --git a/nitric/secrets/secrets.go b/nitric/secrets/client.go similarity index 100% rename from nitric/secrets/secrets.go rename to nitric/secrets/client.go diff --git a/nitric/secrets/secrets_test.go b/nitric/secrets/client_test.go similarity index 100% rename from nitric/secrets/secrets_test.go rename to nitric/secrets/client_test.go diff --git a/nitric/secret.go b/nitric/secrets/secret.go similarity index 81% rename from nitric/secret.go rename to nitric/secrets/secret.go index c041779..db4f953 100644 --- a/nitric/secret.go +++ b/nitric/secrets/secret.go @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package secrets import ( "fmt" - "github.com/nitrictech/go-sdk/nitric/secrets" + "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) @@ -32,23 +32,23 @@ var SecretEverything []SecretPermission = []SecretPermission{SecretAccess, Secre type Secret interface { // Allow requests the given permissions to the secret. - Allow(SecretPermission, ...SecretPermission) (*secrets.SecretClient, error) + Allow(SecretPermission, ...SecretPermission) (*SecretClient, error) } type secret struct { name string - manager *manager - registerChan <-chan RegisterResult + manager *workers.Manager + registerChan <-chan workers.RegisterResult } // NewSecret - Create a new Secret resource func NewSecret(name string) *secret { secret := &secret{ name: name, - manager: defaultManager, + manager: workers.GetDefaultManager(), } - secret.registerChan = defaultManager.registerResource(&v1.ResourceDeclareRequest{ + secret.registerChan = secret.manager.RegisterResource(&v1.ResourceDeclareRequest{ Id: &v1.ResourceIdentifier{ Type: v1.ResourceType_Secret, Name: name, @@ -61,7 +61,7 @@ func NewSecret(name string) *secret { return secret } -func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermission) (*secrets.SecretClient, error) { +func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermission) (*SecretClient, error) { allPerms := append([]SecretPermission{permission}, permissions...) actions := []v1.Action{} @@ -81,10 +81,10 @@ func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermiss return nil, registerResult.Err } - err := s.manager.registerPolicy(registerResult.Identifier, actions...) + err := s.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { return nil, err } - return secrets.NewSecretClient(s.name) + return NewSecretClient(s.name) } diff --git a/nitric/sql.go b/nitric/sql.go deleted file mode 100644 index 1a44b0d..0000000 --- a/nitric/sql.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -import ( - "github.com/nitrictech/go-sdk/nitric/sql" - v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" -) - -type sqlDatabaseOption func(*v1.SqlDatabaseResource) - -func WithMigrationsPath(path string) sqlDatabaseOption { - return func(r *v1.SqlDatabaseResource) { - r.Migrations = &v1.SqlDatabaseMigrations{ - Migrations: &v1.SqlDatabaseMigrations_MigrationsPath{ - MigrationsPath: path, - }, - } - } -} - -// NewSqlDatabase - Create a new Sql Database resource -func NewSqlDatabase(name string, opts ...sqlDatabaseOption) (*sql.SqlClient, error) { - resourceConfig := &v1.ResourceDeclareRequest_SqlDatabase{ - SqlDatabase: &v1.SqlDatabaseResource{}, - } - - for _, opt := range opts { - opt(resourceConfig.SqlDatabase) - } - - registerChan := defaultManager.registerResource(&v1.ResourceDeclareRequest{ - Id: &v1.ResourceIdentifier{ - Type: v1.ResourceType_SqlDatabase, - Name: name, - }, - Config: resourceConfig, - }) - - // Make sure that registerChan is read - // Currently sql databases do not have allow methods so there is no reason to block on this - go func() { - <-registerChan - }() - - return sql.NewSqlClient(name) -} diff --git a/nitric/sql/client.go b/nitric/sql/client.go new file mode 100644 index 0000000..202a848 --- /dev/null +++ b/nitric/sql/client.go @@ -0,0 +1,72 @@ +// Copyright 2023 Nitric Technologies Pty Ltd. +// +// 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 sql + +import ( + "context" + + "google.golang.org/grpc" + + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + + v1 "github.com/nitrictech/nitric/core/pkg/proto/sql/v1" +) + +type SqlClientIface interface { + // Name - The name of the store + Name() string + // Get a value from the store + ConnectionString(context.Context) (string, error) +} + +type SqlClient struct { + name string + sqlClient v1.SqlClient +} + +func (s *SqlClient) Name() string { + return s.name +} + +func (s *SqlClient) ConnectionString(ctx context.Context) (string, error) { + resp, err := s.sqlClient.ConnectionString(ctx, &v1.SqlConnectionStringRequest{ + DatabaseName: s.name, + }) + if err != nil { + return "", err + } + + return resp.ConnectionString, nil +} + +func NewSqlClient(name string) (*SqlClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "unable to reach nitric server", + err, + ) + } + + client := v1.NewSqlClient(conn) + + return &SqlClient{ + name: name, + sqlClient: client, + }, nil +} diff --git a/nitric/sql/sql.go b/nitric/sql/sql.go index 202a848..adc7d8a 100644 --- a/nitric/sql/sql.go +++ b/nitric/sql/sql.go @@ -1,10 +1,10 @@ -// Copyright 2023 Nitric Technologies Pty Ltd. +// Copyright 2021 Nitric Technologies Pty Ltd. // // 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 +// 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, @@ -15,58 +15,45 @@ package sql import ( - "context" - - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/nitric/errors" - "github.com/nitrictech/go-sdk/nitric/errors/codes" - - v1 "github.com/nitrictech/nitric/core/pkg/proto/sql/v1" + "github.com/nitrictech/go-sdk/nitric/workers" + v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) -type SqlClientIface interface { - // Name - The name of the store - Name() string - // Get a value from the store - ConnectionString(context.Context) (string, error) -} - -type SqlClient struct { - name string - sqlClient v1.SqlClient -} +type sqlDatabaseOption func(*v1.SqlDatabaseResource) -func (s *SqlClient) Name() string { - return s.name +func WithMigrationsPath(path string) sqlDatabaseOption { + return func(r *v1.SqlDatabaseResource) { + r.Migrations = &v1.SqlDatabaseMigrations{ + Migrations: &v1.SqlDatabaseMigrations_MigrationsPath{ + MigrationsPath: path, + }, + } + } } -func (s *SqlClient) ConnectionString(ctx context.Context) (string, error) { - resp, err := s.sqlClient.ConnectionString(ctx, &v1.SqlConnectionStringRequest{ - DatabaseName: s.name, - }) - if err != nil { - return "", err +// NewSqlDatabase - Create a new Sql Database resource +func NewSqlDatabase(name string, opts ...sqlDatabaseOption) (*SqlClient, error) { + resourceConfig := &v1.ResourceDeclareRequest_SqlDatabase{ + SqlDatabase: &v1.SqlDatabaseResource{}, } - return resp.ConnectionString, nil -} - -func NewSqlClient(name string) (*SqlClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "unable to reach nitric server", - err, - ) + for _, opt := range opts { + opt(resourceConfig.SqlDatabase) } - client := v1.NewSqlClient(conn) + registerChan := workers.GetDefaultManager().RegisterResource(&v1.ResourceDeclareRequest{ + Id: &v1.ResourceIdentifier{ + Type: v1.ResourceType_SqlDatabase, + Name: name, + }, + Config: resourceConfig, + }) + + // Make sure that registerChan is read + // Currently sql databases do not have allow methods so there is no reason to block on this + go func() { + <-registerChan + }() - return &SqlClient{ - name: name, - sqlClient: client, - }, nil + return NewSqlClient(name) } diff --git a/nitric/storage/bucket.go b/nitric/storage/bucket.go index 142e500..08ddb88 100644 --- a/nitric/storage/bucket.go +++ b/nitric/storage/bucket.go @@ -15,178 +15,124 @@ package storage import ( - "context" - "time" + "fmt" + "strings" - "google.golang.org/grpc" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/nitric/errors" - "github.com/nitrictech/go-sdk/nitric/errors/codes" - v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" + "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/nitric/workers" + v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" + storagepb "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" ) -// Cloud storage bucket resource for large file storage. -type BucketClientIface interface { - // Name - Get the name of the bucket - Name() string - // ListFiles - List the files in the bucket - ListFiles(ctx context.Context) ([]string, error) - // Read - Read this object - Read(ctx context.Context, key string) ([]byte, error) - // Write - Write this object - Write(ctx context.Context, key string, data []byte) error - // Delete - Delete this object - Delete(ctx context.Context, key string) error - // UploadUrl - Creates a signed Url for uploading this file reference - UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) - // DownloadUrl - Creates a signed Url for downloading this file reference - DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) -} - -var _ BucketClientIface = (*BucketClient)(nil) +type BucketPermission string -type BucketClient struct { - storageClient v1.StorageClient - name string +type bucket struct { + name string + manager *workers.Manager + registerChan <-chan workers.RegisterResult } -func (o *BucketClient) Read(ctx context.Context, key string) ([]byte, error) { - r, err := o.storageClient.Read(ctx, &v1.StorageReadRequest{ - BucketName: o.name, - Key: key, - }) - if err != nil { - return nil, errors.FromGrpcError(err) - } - - return r.GetBody(), nil +type Bucket interface { + // Allow requests the given permissions to the bucket. + Allow(BucketPermission, ...BucketPermission) (*BucketClient, error) + + // On registers a handler for a specific event type on the bucket. + // Valid function signatures for handler are: + // + // func() + // func() error + // func(*storage.Ctx) + // func(*storage.Ctx) error + // Handler[storage.Ctx] + On(eventType EventType, notificationPrefixFilter string, handler interface{}) } -func (o *BucketClient) Write(ctx context.Context, key string, content []byte) error { - if _, err := o.storageClient.Write(ctx, &v1.StorageWriteRequest{ - BucketName: o.name, - Key: key, - Body: content, - }); err != nil { - return errors.FromGrpcError(err) - } +const ( + BucketRead BucketPermission = "read" + BucketWrite BucketPermission = "write" + BucketDelete BucketPermission = "delete" +) - return nil -} +var BucketEverything []BucketPermission = []BucketPermission{BucketRead, BucketWrite, BucketDelete} -func (o *BucketClient) Delete(ctx context.Context, key string) error { - if _, err := o.storageClient.Delete(ctx, &v1.StorageDeleteRequest{ - BucketName: o.name, - Key: key, - }); err != nil { - return errors.FromGrpcError(err) +// NewBucket - Create a new Bucket resource +func NewBucket(name string) Bucket { + bucket := &bucket{ + name: name, + manager: workers.GetDefaultManager(), } - return nil -} - -func (b *BucketClient) ListFiles(ctx context.Context) ([]string, error) { - resp, err := b.storageClient.ListBlobs(ctx, &v1.StorageListBlobsRequest{ - BucketName: b.name, + bucket.registerChan = bucket.manager.RegisterResource(&v1.ResourceDeclareRequest{ + Id: &v1.ResourceIdentifier{ + Type: v1.ResourceType_Bucket, + Name: name, + }, + Config: &v1.ResourceDeclareRequest_Bucket{ + Bucket: &v1.BucketResource{}, + }, }) - if err != nil { - return nil, err - } - - fileRefs := make([]string, 0) - - for _, f := range resp.Blobs { - fileRefs = append(fileRefs, f.Key) - } - - return fileRefs, nil -} -type Mode int - -const ( - ModeRead Mode = iota - ModeWrite -) - -type presignUrlOptions struct { - mode Mode - expiry time.Duration + return bucket } -type PresignUrlOption func(opts *presignUrlOptions) - -func WithPresignUrlExpiry(expiry time.Duration) PresignUrlOption { - return func(opts *presignUrlOptions) { - opts.expiry = expiry +func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) (*BucketClient, error) { + allPerms := append([]BucketPermission{permission}, permissions...) + + actions := []v1.Action{} + for _, perm := range allPerms { + switch perm { + case BucketRead: + actions = append(actions, v1.Action_BucketFileGet, v1.Action_BucketFileList) + case BucketWrite: + actions = append(actions, v1.Action_BucketFilePut) + case BucketDelete: + actions = append(actions, v1.Action_BucketFileDelete) + default: + return nil, fmt.Errorf("bucketPermission %s unknown", perm) + } } -} -func getPresignUrlOpts(mode Mode, opts ...PresignUrlOption) *presignUrlOptions { - defaultOpts := &presignUrlOptions{ - mode: mode, - expiry: time.Minute * 5, + registerResult := <-b.registerChan + if registerResult.Err != nil { + return nil, registerResult.Err } - for _, opt := range opts { - opt(defaultOpts) + err := b.manager.RegisterPolicy(registerResult.Identifier, actions...) + if err != nil { + return nil, err } - return defaultOpts -} - -func (o *BucketClient) UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { - optsWithDefaults := getPresignUrlOpts(ModeWrite, opts...) - - return o.signUrl(ctx, key, optsWithDefaults) + return NewBucketClient(b.name) } -func (o *BucketClient) DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { - optsWithDefaults := getPresignUrlOpts(ModeRead, opts...) - - return o.signUrl(ctx, key, optsWithDefaults) -} - -func (o *BucketClient) signUrl(ctx context.Context, key string, opts *presignUrlOptions) (string, error) { - op := v1.StoragePreSignUrlRequest_READ +func (b *bucket) On(eventType EventType, notificationPrefixFilter string, handler interface{}) { + var blobEventType storagepb.BlobEventType + switch eventType { + case WriteNotification: + blobEventType = storagepb.BlobEventType_Created + case DeleteNotification: + blobEventType = storagepb.BlobEventType_Deleted + } - if opts.mode == ModeWrite { - op = v1.StoragePreSignUrlRequest_WRITE + registrationRequest := &storagepb.RegistrationRequest{ + BucketName: b.name, + BlobEventType: blobEventType, + KeyPrefixFilter: notificationPrefixFilter, } - r, err := o.storageClient.PreSignUrl(ctx, &v1.StoragePreSignUrlRequest{ - BucketName: o.name, - Key: key, - Operation: op, - Expiry: durationpb.New(opts.expiry), - }) + typedHandler, err := handlers.HandlerFromInterface[Ctx](handler) if err != nil { - return "", errors.FromGrpcError(err) + panic(err) } - return r.Url, nil -} - -func (b *BucketClient) Name() string { - return b.name -} - -func NewBucketClient(name string) (*BucketClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "NewBucketClient: unable to reach nitric server", - err, - ) + opts := &bucketEventWorkerOpts{ + RegistrationRequest: registrationRequest, + Handler: typedHandler, } - storageClient := v1.NewStorageClient(conn) + worker := newBucketEventWorker(opts) - return &BucketClient{ - name: name, - storageClient: storageClient, - }, nil + b.manager.AddWorker("bucketNotification:"+strings.Join([]string{ + b.name, notificationPrefixFilter, string(eventType), + }, "-"), worker) } diff --git a/nitric/bucket_workers.go b/nitric/storage/bucket_workers.go similarity index 92% rename from nitric/bucket_workers.go rename to nitric/storage/bucket_workers.go index 30ad379..e6dc477 100644 --- a/nitric/bucket_workers.go +++ b/nitric/storage/bucket_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package storage import ( "context" @@ -24,18 +24,18 @@ import ( "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/storage" + "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" ) type bucketEventWorker struct { client v1.StorageListenerClient registrationRequest *v1.RegistrationRequest - handler Handler[storage.Ctx] + handler handlers.Handler[Ctx] } type bucketEventWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Handler Handler[storage.Ctx] + Handler handlers.Handler[Ctx] } // Start implements Worker. @@ -57,7 +57,7 @@ func (b *bucketEventWorker) Start(ctx context.Context) error { return err } for { - var ctx *storage.Ctx + var ctx *Ctx resp, err := stream.Recv() @@ -71,7 +71,7 @@ func (b *bucketEventWorker) Start(ctx context.Context) error { } else if err == nil && resp.GetRegistrationResponse() != nil { // There is no need to respond to the registration response } else if err == nil && resp.GetBlobEventRequest() != nil { - ctx = storage.NewCtx(resp) + ctx = NewCtx(resp) err = b.handler(ctx) if err != nil { ctx.WithError(err) diff --git a/nitric/storage/client.go b/nitric/storage/client.go new file mode 100644 index 0000000..142e500 --- /dev/null +++ b/nitric/storage/client.go @@ -0,0 +1,192 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 storage + +import ( + "context" + "time" + + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/durationpb" + + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" +) + +// Cloud storage bucket resource for large file storage. +type BucketClientIface interface { + // Name - Get the name of the bucket + Name() string + // ListFiles - List the files in the bucket + ListFiles(ctx context.Context) ([]string, error) + // Read - Read this object + Read(ctx context.Context, key string) ([]byte, error) + // Write - Write this object + Write(ctx context.Context, key string, data []byte) error + // Delete - Delete this object + Delete(ctx context.Context, key string) error + // UploadUrl - Creates a signed Url for uploading this file reference + UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) + // DownloadUrl - Creates a signed Url for downloading this file reference + DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) +} + +var _ BucketClientIface = (*BucketClient)(nil) + +type BucketClient struct { + storageClient v1.StorageClient + name string +} + +func (o *BucketClient) Read(ctx context.Context, key string) ([]byte, error) { + r, err := o.storageClient.Read(ctx, &v1.StorageReadRequest{ + BucketName: o.name, + Key: key, + }) + if err != nil { + return nil, errors.FromGrpcError(err) + } + + return r.GetBody(), nil +} + +func (o *BucketClient) Write(ctx context.Context, key string, content []byte) error { + if _, err := o.storageClient.Write(ctx, &v1.StorageWriteRequest{ + BucketName: o.name, + Key: key, + Body: content, + }); err != nil { + return errors.FromGrpcError(err) + } + + return nil +} + +func (o *BucketClient) Delete(ctx context.Context, key string) error { + if _, err := o.storageClient.Delete(ctx, &v1.StorageDeleteRequest{ + BucketName: o.name, + Key: key, + }); err != nil { + return errors.FromGrpcError(err) + } + + return nil +} + +func (b *BucketClient) ListFiles(ctx context.Context) ([]string, error) { + resp, err := b.storageClient.ListBlobs(ctx, &v1.StorageListBlobsRequest{ + BucketName: b.name, + }) + if err != nil { + return nil, err + } + + fileRefs := make([]string, 0) + + for _, f := range resp.Blobs { + fileRefs = append(fileRefs, f.Key) + } + + return fileRefs, nil +} + +type Mode int + +const ( + ModeRead Mode = iota + ModeWrite +) + +type presignUrlOptions struct { + mode Mode + expiry time.Duration +} + +type PresignUrlOption func(opts *presignUrlOptions) + +func WithPresignUrlExpiry(expiry time.Duration) PresignUrlOption { + return func(opts *presignUrlOptions) { + opts.expiry = expiry + } +} + +func getPresignUrlOpts(mode Mode, opts ...PresignUrlOption) *presignUrlOptions { + defaultOpts := &presignUrlOptions{ + mode: mode, + expiry: time.Minute * 5, + } + + for _, opt := range opts { + opt(defaultOpts) + } + + return defaultOpts +} + +func (o *BucketClient) UploadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { + optsWithDefaults := getPresignUrlOpts(ModeWrite, opts...) + + return o.signUrl(ctx, key, optsWithDefaults) +} + +func (o *BucketClient) DownloadUrl(ctx context.Context, key string, opts ...PresignUrlOption) (string, error) { + optsWithDefaults := getPresignUrlOpts(ModeRead, opts...) + + return o.signUrl(ctx, key, optsWithDefaults) +} + +func (o *BucketClient) signUrl(ctx context.Context, key string, opts *presignUrlOptions) (string, error) { + op := v1.StoragePreSignUrlRequest_READ + + if opts.mode == ModeWrite { + op = v1.StoragePreSignUrlRequest_WRITE + } + + r, err := o.storageClient.PreSignUrl(ctx, &v1.StoragePreSignUrlRequest{ + BucketName: o.name, + Key: key, + Operation: op, + Expiry: durationpb.New(opts.expiry), + }) + if err != nil { + return "", errors.FromGrpcError(err) + } + + return r.Url, nil +} + +func (b *BucketClient) Name() string { + return b.name +} + +func NewBucketClient(name string) (*BucketClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "NewBucketClient: unable to reach nitric server", + err, + ) + } + + storageClient := v1.NewStorageClient(conn) + + return &BucketClient{ + name: name, + storageClient: storageClient, + }, nil +} diff --git a/nitric/storage/bucket_test.go b/nitric/storage/client_test.go similarity index 100% rename from nitric/storage/bucket_test.go rename to nitric/storage/client_test.go diff --git a/nitric/topic.go b/nitric/topic.go deleted file mode 100644 index 5dbc3e8..0000000 --- a/nitric/topic.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2021 Nitric Technologies Pty Ltd. -// -// 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 nitric - -import ( - "fmt" - - "github.com/nitrictech/go-sdk/nitric/topics" - - v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" - topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" -) - -// TopicPermission defines the available permissions on a topic -type TopicPermission string - -const ( - // TopicPublish is required to call Publish on a topic. - TopicPublish TopicPermission = "publish" -) - -type SubscribableTopic interface { - // Allow requests the given permissions to the topic. - Allow(TopicPermission, ...TopicPermission) (*topics.TopicClient, error) - - // Subscribe will register and start a subscription handler that will be called for all events from this topic. - // Valid function signatures for handler are: - // - // func() - // func() error - // func(*topics.Ctx) - // func(*topics.Ctx) error - // Handler[topics.Ctx] - Subscribe(interface{}) -} - -type subscribableTopic struct { - name string - manager *manager - registerChan <-chan RegisterResult -} - -// NewTopic creates a new Topic with the give name. -func NewTopic(name string) SubscribableTopic { - topic := &subscribableTopic{ - name: name, - manager: defaultManager, - } - - topic.registerChan = defaultManager.registerResource(&v1.ResourceDeclareRequest{ - Id: &v1.ResourceIdentifier{ - Type: v1.ResourceType_Topic, - Name: name, - }, - Config: &v1.ResourceDeclareRequest_Topic{ - Topic: &v1.TopicResource{}, - }, - }) - - return topic -} - -func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...TopicPermission) (*topics.TopicClient, error) { - allPerms := append([]TopicPermission{permission}, permissions...) - - actions := []v1.Action{} - for _, perm := range allPerms { - switch perm { - case TopicPublish: - actions = append(actions, v1.Action_TopicPublish) - default: - return nil, fmt.Errorf("TopicPermission %s unknown", perm) - } - } - - registerResult := <-t.registerChan - if registerResult.Err != nil { - return nil, registerResult.Err - } - - err := t.manager.registerPolicy(registerResult.Identifier, actions...) - if err != nil { - return nil, err - } - - return topics.NewTopicClient(t.name) -} - -func (t *subscribableTopic) Subscribe(handler interface{}) { - registrationRequest := &topicspb.RegistrationRequest{ - TopicName: t.name, - } - - typedHandler, err := interfaceToHandler[topics.Ctx](handler) - if err != nil { - panic(err) - } - - opts := &subscriptionWorkerOpts{ - RegistrationRequest: registrationRequest, - Handler: typedHandler, - } - - worker := newSubscriptionWorker(opts) - t.manager.addWorker("SubscriptionWorker:"+t.name, worker) -} diff --git a/nitric/topics/client.go b/nitric/topics/client.go new file mode 100644 index 0000000..a256b82 --- /dev/null +++ b/nitric/topics/client.go @@ -0,0 +1,102 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 topics + +import ( + "context" + "time" + + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/durationpb" + + "github.com/nitrictech/go-sdk/constants" + "github.com/nitrictech/go-sdk/nitric/errors" + "github.com/nitrictech/go-sdk/nitric/errors/codes" + v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" + "github.com/nitrictech/protoutils" +) + +type PublishOption = func(*v1.TopicPublishRequest) + +// TopicClientIface for pub/sub async messaging. +type TopicClientIface interface { + // Name returns the Topic name. + Name() string + + // Publish will publish the provided events on the topic. + Publish(context.Context, map[string]interface{}, ...PublishOption) error +} + +type TopicClient struct { + name string + topicClient v1.TopicsClient +} + +func (s *TopicClient) Name() string { + return s.name +} + +// WithDelay - Delay event publishing by the given duration +func WithDelay(duration time.Duration) func(*v1.TopicPublishRequest) { + return func(epr *v1.TopicPublishRequest) { + epr.Delay = durationpb.New(duration) + } +} + +func (s *TopicClient) Publish(ctx context.Context, message map[string]interface{}, opts ...PublishOption) error { + payloadStruct, err := protoutils.NewStruct(message) + if err != nil { + return errors.NewWithCause(codes.InvalidArgument, "Topic.Publish", err) + } + + event := &v1.TopicPublishRequest{ + TopicName: s.name, + Message: &v1.TopicMessage{ + Content: &v1.TopicMessage_StructPayload{ + StructPayload: payloadStruct, + }, + }, + } + + // Apply options to the event payload + for _, opt := range opts { + opt(event) + } + + _, err = s.topicClient.Publish(ctx, event) + if err != nil { + return errors.FromGrpcError(err) + } + + return nil +} + +func NewTopicClient(name string) (*TopicClient, error) { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, errors.NewWithCause( + codes.Unavailable, + "NewTopicClient: unable to reach nitric server", + err, + ) + } + + topicClient := v1.NewTopicsClient(conn) + + return &TopicClient{ + name: name, + topicClient: topicClient, + }, nil +} diff --git a/nitric/topics/topic_test.go b/nitric/topics/client_test.go similarity index 100% rename from nitric/topics/topic_test.go rename to nitric/topics/client_test.go diff --git a/nitric/topics/topic.go b/nitric/topics/topic.go index a256b82..65ddca0 100644 --- a/nitric/topics/topic.go +++ b/nitric/topics/topic.go @@ -15,88 +15,104 @@ package topics import ( - "context" - "time" + "fmt" - "google.golang.org/grpc" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/nitrictech/go-sdk/constants" - "github.com/nitrictech/go-sdk/nitric/errors" - "github.com/nitrictech/go-sdk/nitric/errors/codes" - v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" - "github.com/nitrictech/protoutils" + "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/nitric/workers" + v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" + topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" ) -type PublishOption = func(*v1.TopicPublishRequest) - -// TopicClientIface for pub/sub async messaging. -type TopicClientIface interface { - // Name returns the Topic name. - Name() string - - // Publish will publish the provided events on the topic. - Publish(context.Context, map[string]interface{}, ...PublishOption) error -} +// TopicPermission defines the available permissions on a topic +type TopicPermission string -type TopicClient struct { - name string - topicClient v1.TopicsClient -} +const ( + // TopicPublish is required to call Publish on a topic. + TopicPublish TopicPermission = "publish" +) -func (s *TopicClient) Name() string { - return s.name +type SubscribableTopic interface { + // Allow requests the given permissions to the topic. + Allow(TopicPermission, ...TopicPermission) (*TopicClient, error) + + // Subscribe will register and start a subscription handler that will be called for all events from this topic. + // Valid function signatures for handler are: + // + // func() + // func() error + // func(*topics.Ctx) + // func(*topics.Ctx) error + // Handler[topics.Ctx] + Subscribe(interface{}) } -// WithDelay - Delay event publishing by the given duration -func WithDelay(duration time.Duration) func(*v1.TopicPublishRequest) { - return func(epr *v1.TopicPublishRequest) { - epr.Delay = durationpb.New(duration) - } +type subscribableTopic struct { + name string + manager *workers.Manager + registerChan <-chan workers.RegisterResult } -func (s *TopicClient) Publish(ctx context.Context, message map[string]interface{}, opts ...PublishOption) error { - payloadStruct, err := protoutils.NewStruct(message) - if err != nil { - return errors.NewWithCause(codes.InvalidArgument, "Topic.Publish", err) +// NewTopic creates a new Topic with the give name. +func NewTopic(name string) SubscribableTopic { + topic := &subscribableTopic{ + name: name, + manager: workers.GetDefaultManager(), } - event := &v1.TopicPublishRequest{ - TopicName: s.name, - Message: &v1.TopicMessage{ - Content: &v1.TopicMessage_StructPayload{ - StructPayload: payloadStruct, - }, + topic.registerChan = topic.manager.RegisterResource(&v1.ResourceDeclareRequest{ + Id: &v1.ResourceIdentifier{ + Type: v1.ResourceType_Topic, + Name: name, }, + Config: &v1.ResourceDeclareRequest_Topic{ + Topic: &v1.TopicResource{}, + }, + }) + + return topic +} + +func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...TopicPermission) (*TopicClient, error) { + allPerms := append([]TopicPermission{permission}, permissions...) + + actions := []v1.Action{} + for _, perm := range allPerms { + switch perm { + case TopicPublish: + actions = append(actions, v1.Action_TopicPublish) + default: + return nil, fmt.Errorf("TopicPermission %s unknown", perm) + } } - // Apply options to the event payload - for _, opt := range opts { - opt(event) + registerResult := <-t.registerChan + if registerResult.Err != nil { + return nil, registerResult.Err } - _, err = s.topicClient.Publish(ctx, event) + err := t.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return errors.FromGrpcError(err) + return nil, err } - return nil + return NewTopicClient(t.name) } -func NewTopicClient(name string) (*TopicClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) +func (t *subscribableTopic) Subscribe(handler interface{}) { + registrationRequest := &topicspb.RegistrationRequest{ + TopicName: t.name, + } + + typedHandler, err := handlers.HandlerFromInterface[Ctx](handler) if err != nil { - return nil, errors.NewWithCause( - codes.Unavailable, - "NewTopicClient: unable to reach nitric server", - err, - ) + panic(err) } - topicClient := v1.NewTopicsClient(conn) + opts := &subscriptionWorkerOpts{ + RegistrationRequest: registrationRequest, + Handler: typedHandler, + } - return &TopicClient{ - name: name, - topicClient: topicClient, - }, nil + worker := newSubscriptionWorker(opts) + t.manager.AddWorker("SubscriptionWorker:"+t.name, worker) } diff --git a/nitric/topic_workers.go b/nitric/topics/topic_workers.go similarity index 92% rename from nitric/topic_workers.go rename to nitric/topics/topic_workers.go index 18e5bed..dadcf04 100644 --- a/nitric/topic_workers.go +++ b/nitric/topics/topic_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package topics import ( "context" @@ -25,18 +25,18 @@ import ( "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/topics" + "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" ) type subscriptionWorker struct { client v1.SubscriberClient registrationRequest *v1.RegistrationRequest - handler Handler[topics.Ctx] + handler handlers.Handler[Ctx] } type subscriptionWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Handler Handler[topics.Ctx] + Handler handlers.Handler[Ctx] } // Start implements Worker. @@ -58,7 +58,7 @@ func (s *subscriptionWorker) Start(ctx context.Context) error { return err } for { - var ctx *topics.Ctx + var ctx *Ctx resp, err := stream.Recv() @@ -72,7 +72,7 @@ func (s *subscriptionWorker) Start(ctx context.Context) error { } else if err == nil && resp.GetRegistrationResponse() != nil { // There is no need to respond to the registration response } else if err == nil && resp.GetMessageRequest() != nil { - ctx = topics.NewCtx(resp) + ctx = NewCtx(resp) err = s.handler(ctx) if err != nil { ctx.WithError(err) diff --git a/nitric/websocket.go b/nitric/websockets/websocket.go similarity index 79% rename from nitric/websocket.go rename to nitric/websockets/websocket.go index f77b520..691e2ae 100644 --- a/nitric/websocket.go +++ b/nitric/websockets/websocket.go @@ -12,13 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package websockets import ( "context" "strings" - "github.com/nitrictech/go-sdk/nitric/websockets" + "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/nitric/workers" resourcesv1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" websocketsv1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) @@ -35,7 +36,7 @@ type Websocket interface { // func(*websocket.Ctx) // func(*websocket.Ctx) error // Handler[websocket.Ctx] - On(eventType websockets.EventType, handler interface{}) + On(eventType EventType, handler interface{}) // Send a message to a specific connection Send(ctx context.Context, connectionId string, message []byte) error // Close a specific connection @@ -46,13 +47,15 @@ type websocket struct { Websocket name string - manager *manager + manager *workers.Manager client websocketsv1.WebsocketClient } // NewWebsocket - Create a new Websocket API resource func NewWebsocket(name string) (Websocket, error) { - registerResult := <-defaultManager.registerResource(&resourcesv1.ResourceDeclareRequest{ + manager := workers.GetDefaultManager() + + registerResult := <-manager.RegisterResource(&resourcesv1.ResourceDeclareRequest{ Id: &resourcesv1.ResourceIdentifier{ Type: resourcesv1.ResourceType_Websocket, Name: name, @@ -64,15 +67,20 @@ func NewWebsocket(name string) (Websocket, error) { actions := []resourcesv1.Action{resourcesv1.Action_WebsocketManage} - err := defaultManager.registerPolicy(registerResult.Identifier, actions...) + err := manager.RegisterPolicy(registerResult.Identifier, actions...) + if err != nil { + return nil, err + } + + conn, err := manager.GetConnection() if err != nil { return nil, err } - wClient := websocketsv1.NewWebsocketClient(defaultManager.conn) + wClient := websocketsv1.NewWebsocketClient(conn) return &websocket{ - manager: defaultManager, + manager: manager, client: wClient, name: name, }, nil @@ -82,12 +90,12 @@ func (w *websocket) Name() string { return w.name } -func (w *websocket) On(eventType websockets.EventType, handler interface{}) { +func (w *websocket) On(eventType EventType, handler interface{}) { var _eventType websocketsv1.WebsocketEventType switch eventType { - case websockets.EventType_Disconnect: + case EventType_Disconnect: _eventType = websocketsv1.WebsocketEventType_Disconnect - case websockets.EventType_Message: + case EventType_Message: _eventType = websocketsv1.WebsocketEventType_Message default: _eventType = websocketsv1.WebsocketEventType_Connect @@ -98,7 +106,7 @@ func (w *websocket) On(eventType websockets.EventType, handler interface{}) { EventType: _eventType, } - typedHandler, err := interfaceToHandler[websockets.Ctx](handler) + typedHandler, err := handlers.HandlerFromInterface[Ctx](handler) if err != nil { panic(err) } @@ -109,7 +117,7 @@ func (w *websocket) On(eventType websockets.EventType, handler interface{}) { } worker := newWebsocketWorker(opts) - w.manager.addWorker("WebsocketWorker:"+strings.Join([]string{ + w.manager.AddWorker("WebsocketWorker:"+strings.Join([]string{ w.name, string(eventType), }, "-"), worker) diff --git a/nitric/websocket_workers.go b/nitric/websockets/websocket_workers.go similarity index 92% rename from nitric/websocket_workers.go rename to nitric/websockets/websocket_workers.go index d23c75a..d7e19ce 100644 --- a/nitric/websocket_workers.go +++ b/nitric/websockets/websocket_workers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package websockets import ( "context" @@ -24,18 +24,18 @@ import ( "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/websockets" + "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) type websocketWorker struct { client v1.WebsocketHandlerClient registrationRequest *v1.RegistrationRequest - handler Handler[websockets.Ctx] + handler handlers.Handler[Ctx] } type websocketWorkerOpts struct { RegistrationRequest *v1.RegistrationRequest - Handler Handler[websockets.Ctx] + Handler handlers.Handler[Ctx] } // Start implements Worker. @@ -57,7 +57,7 @@ func (w *websocketWorker) Start(ctx context.Context) error { return err } for { - var ctx *websockets.Ctx + var ctx *Ctx resp, err := stream.Recv() @@ -71,7 +71,7 @@ func (w *websocketWorker) Start(ctx context.Context) error { } else if err == nil && resp.GetRegistrationResponse() != nil { // There is no need to respond to the registration response } else if err == nil && resp.GetWebsocketEventRequest() != nil { - ctx = websockets.NewCtx(resp) + ctx = NewCtx(resp) err = w.handler(ctx) if err != nil { ctx.WithError(err) diff --git a/nitric/manager.go b/nitric/workers/manager.go similarity index 73% rename from nitric/manager.go rename to nitric/workers/manager.go index 88b2abe..594e0b3 100644 --- a/nitric/manager.go +++ b/nitric/workers/manager.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package workers import ( "context" @@ -35,8 +35,8 @@ type RegisterResult struct { Err error } -type manager struct { - workers map[string]streamWorker +type Manager struct { + workers map[string]StreamWorker conn grpc.ClientConnInterface connMutex sync.Mutex @@ -45,20 +45,24 @@ type manager struct { var defaultManager = New() +func GetDefaultManager() *Manager { + return defaultManager +} + // New is used to create the top level resource manager. // Note: this is not required if you are using // resources.NewApi() and the like. These use a default manager instance. -func New() *manager { - return &manager{ - workers: map[string]streamWorker{}, +func New() *Manager { + return &Manager{ + workers: map[string]StreamWorker{}, } } -func (m *manager) addWorker(name string, s streamWorker) { +func (m *Manager) AddWorker(name string, s StreamWorker) { m.workers[name] = s } -func (m *manager) resourceServiceClient() (v1.ResourcesClient, error) { +func (m *Manager) GetConnection() (grpc.ClientConnInterface, error) { m.connMutex.Lock() defer m.connMutex.Unlock() @@ -69,13 +73,23 @@ func (m *manager) resourceServiceClient() (v1.ResourcesClient, error) { } m.conn = conn } + + return m.conn, nil +} + +func (m *Manager) resourceServiceClient() (v1.ResourcesClient, error) { + conn, err := m.GetConnection() + if err != nil { + return nil, err + } + if m.rsc == nil { - m.rsc = v1.NewResourcesClient(m.conn) + m.rsc = v1.NewResourcesClient(conn) } return m.rsc, nil } -func (m *manager) registerResource(request *v1.ResourceDeclareRequest) <-chan RegisterResult { +func (m *Manager) RegisterResource(request *v1.ResourceDeclareRequest) <-chan RegisterResult { registerResourceChan := make(chan RegisterResult) go func() { @@ -108,7 +122,26 @@ func (m *manager) registerResource(request *v1.ResourceDeclareRequest) <-chan Re return registerResourceChan } -func (m *manager) registerPolicy(res *v1.ResourceIdentifier, actions ...v1.Action) error { +func functionResourceDeclareRequest(subject *v1.ResourceIdentifier, actions []v1.Action) *v1.ResourceDeclareRequest { + return &v1.ResourceDeclareRequest{ + Id: &v1.ResourceIdentifier{ + Type: v1.ResourceType_Policy, + }, + Config: &v1.ResourceDeclareRequest_Policy{ + Policy: &v1.PolicyResource{ + Principals: []*v1.ResourceIdentifier{ + { + Type: v1.ResourceType_Service, + }, + }, + Actions: actions, + Resources: []*v1.ResourceIdentifier{subject}, + }, + }, + } +} + +func (m *Manager) RegisterPolicy(res *v1.ResourceIdentifier, actions ...v1.Action) error { rsc, err := m.resourceServiceClient() if err != nil { return err @@ -127,13 +160,13 @@ func Run() error { return defaultManager.run() } -func (m *manager) run() error { +func (m *Manager) run() error { wg := sync.WaitGroup{} errList := &multierror.ErrorList{} for _, worker := range m.workers { wg.Add(1) - go func(s streamWorker) { + go func(s StreamWorker) { defer wg.Done() if err := s.Start(context.TODO()); err != nil { diff --git a/nitric/workers.go b/nitric/workers/workers.go similarity index 93% rename from nitric/workers.go rename to nitric/workers/workers.go index 2f7e131..a8d0f81 100644 --- a/nitric/workers.go +++ b/nitric/workers/workers.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package nitric +package workers import "context" -type streamWorker interface { +type StreamWorker interface { Start(context.Context) error } From 093b3b4360142edbc17093b9a7de73dc2940bd59 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 1 Oct 2024 16:05:22 +1000 Subject: [PATCH 28/42] use single grpc connection to nitric server --- internal/grpc/grpcx.go | 33 +++++++++++++++++++++++++ nitric/apis/workers.go | 6 ++--- nitric/keyvalue/client.go | 6 ++--- nitric/queues/client.go | 6 ++--- nitric/schedules/schedule_workers.go | 6 ++--- nitric/secrets/client.go | 6 ++--- nitric/sql/client.go | 6 ++--- nitric/storage/bucket_workers.go | 6 ++--- nitric/storage/client.go | 5 ++-- nitric/topics/client.go | 5 ++-- nitric/topics/topic_workers.go | 6 ++--- nitric/websockets/websocket_workers.go | 34 +++++++++++++------------- nitric/workers/manager.go | 24 +++--------------- 13 files changed, 73 insertions(+), 76 deletions(-) create mode 100644 internal/grpc/grpcx.go diff --git a/internal/grpc/grpcx.go b/internal/grpc/grpcx.go new file mode 100644 index 0000000..4cf4cb7 --- /dev/null +++ b/internal/grpc/grpcx.go @@ -0,0 +1,33 @@ +package grpcx + +import ( + "sync" + + "github.com/nitrictech/go-sdk/constants" + "google.golang.org/grpc" +) + +type grpcManager struct { + conn grpc.ClientConnInterface + connMutex sync.Mutex +} + +var m = grpcManager{ + conn: nil, + connMutex: sync.Mutex{}, +} + +func GetConnection() (grpc.ClientConnInterface, error) { + m.connMutex.Lock() + defer m.connMutex.Unlock() + + if m.conn == nil { + conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + if err != nil { + return nil, err + } + m.conn = conn + } + + return m.conn, nil +} diff --git a/nitric/apis/workers.go b/nitric/apis/workers.go index bddec64..7a7df9d 100644 --- a/nitric/apis/workers.go +++ b/nitric/apis/workers.go @@ -19,9 +19,7 @@ import ( errorsstd "errors" "io" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/go-sdk/nitric/handlers" @@ -93,7 +91,7 @@ func (a *apiWorker) Start(ctx context.Context) error { } func newApiWorker(opts *apiWorkerOpts) *apiWorker { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/keyvalue/client.go b/nitric/keyvalue/client.go index 538c0e3..4e0d714 100644 --- a/nitric/keyvalue/client.go +++ b/nitric/keyvalue/client.go @@ -17,9 +17,7 @@ package keyvalue import ( "context" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/protoutils" @@ -161,7 +159,7 @@ func (s *KvStoreClient) Keys(ctx context.Context, opts ...ScanKeysOption) (*KeyS } func NewKvStoreClient(name string) (*KvStoreClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/nitric/queues/client.go b/nitric/queues/client.go index 93a24de..4cf404d 100644 --- a/nitric/queues/client.go +++ b/nitric/queues/client.go @@ -17,9 +17,7 @@ package queues import ( "context" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/queues/v1" @@ -108,7 +106,7 @@ func (q *QueueClient) Enqueue(ctx context.Context, messages []map[string]interfa } func NewQueueClient(name string) (*QueueClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/nitric/schedules/schedule_workers.go b/nitric/schedules/schedule_workers.go index 0dc1399..9959806 100644 --- a/nitric/schedules/schedule_workers.go +++ b/nitric/schedules/schedule_workers.go @@ -19,9 +19,7 @@ import ( errorsstd "errors" "io" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/go-sdk/nitric/handlers" @@ -88,7 +86,7 @@ func (i *scheduleWorker) Start(ctx context.Context) error { } func newScheduleWorker(opts *scheduleWorkerOpts) *scheduleWorker { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/secrets/client.go b/nitric/secrets/client.go index ea5d628..5f43b23 100644 --- a/nitric/secrets/client.go +++ b/nitric/secrets/client.go @@ -17,9 +17,7 @@ package secrets import ( "context" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/secrets/v1" @@ -95,7 +93,7 @@ func (s *SecretClient) AccessVersion(ctx context.Context, version string) (Secre } func NewSecretClient(name string) (*SecretClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/nitric/sql/client.go b/nitric/sql/client.go index 202a848..d50e781 100644 --- a/nitric/sql/client.go +++ b/nitric/sql/client.go @@ -17,9 +17,7 @@ package sql import ( "context" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" @@ -54,7 +52,7 @@ func (s *SqlClient) ConnectionString(ctx context.Context) (string, error) { } func NewSqlClient(name string) (*SqlClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/nitric/storage/bucket_workers.go b/nitric/storage/bucket_workers.go index e6dc477..6f817d2 100644 --- a/nitric/storage/bucket_workers.go +++ b/nitric/storage/bucket_workers.go @@ -19,9 +19,7 @@ import ( errorsstd "errors" "io" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/go-sdk/nitric/handlers" @@ -88,7 +86,7 @@ func (b *bucketEventWorker) Start(ctx context.Context) error { } func newBucketEventWorker(opts *bucketEventWorkerOpts) *bucketEventWorker { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/storage/client.go b/nitric/storage/client.go index 142e500..1a4ab76 100644 --- a/nitric/storage/client.go +++ b/nitric/storage/client.go @@ -18,10 +18,9 @@ import ( "context" "time" - "google.golang.org/grpc" "google.golang.org/protobuf/types/known/durationpb" - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" @@ -174,7 +173,7 @@ func (b *BucketClient) Name() string { } func NewBucketClient(name string) (*BucketClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/nitric/topics/client.go b/nitric/topics/client.go index a256b82..63aa4bb 100644 --- a/nitric/topics/client.go +++ b/nitric/topics/client.go @@ -18,10 +18,9 @@ import ( "context" "time" - "google.golang.org/grpc" "google.golang.org/protobuf/types/known/durationpb" - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" @@ -84,7 +83,7 @@ func (s *TopicClient) Publish(ctx context.Context, message map[string]interface{ } func NewTopicClient(name string) (*TopicClient, error) { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { return nil, errors.NewWithCause( codes.Unavailable, diff --git a/nitric/topics/topic_workers.go b/nitric/topics/topic_workers.go index dadcf04..af00678 100644 --- a/nitric/topics/topic_workers.go +++ b/nitric/topics/topic_workers.go @@ -18,11 +18,9 @@ import ( "context" "io" - "google.golang.org/grpc" - errorsstd "errors" - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/go-sdk/nitric/handlers" @@ -89,7 +87,7 @@ func (s *subscriptionWorker) Start(ctx context.Context) error { } func newSubscriptionWorker(opts *subscriptionWorkerOpts) *subscriptionWorker { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) + conn, err := grpcx.GetConnection() if err != nil { panic(errors.NewWithCause( codes.Unavailable, diff --git a/nitric/websockets/websocket_workers.go b/nitric/websockets/websocket_workers.go index d7e19ce..31deede 100644 --- a/nitric/websockets/websocket_workers.go +++ b/nitric/websockets/websocket_workers.go @@ -19,12 +19,10 @@ import ( errorsstd "errors" "io" - "google.golang.org/grpc" - - "github.com/nitrictech/go-sdk/constants" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) @@ -87,21 +85,23 @@ func (w *websocketWorker) Start(ctx context.Context) error { } } -func newWebsocketWorker(opts *websocketWorkerOpts) *websocketWorker { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - panic(errors.NewWithCause( - codes.Unavailable, - "NewWebsocketWorker: Unable to reach WebsocketHandlerClient", - err, - )) - } +func newWebsocketWorker(opts *websocketWorkerOpts) func(m *workers.Manager) *websocketWorker { + return func(m *workers.Manager) *websocketWorker { + conn, err := m.GetConnection() + if err != nil { + panic(errors.NewWithCause( + codes.Unavailable, + "NewWebsocketWorker: Unable to reach WebsocketHandlerClient", + err, + )) + } - client := v1.NewWebsocketHandlerClient(conn) + client := v1.NewWebsocketHandlerClient(conn) - return &websocketWorker{ - client: client, - registrationRequest: opts.RegistrationRequest, - handler: opts.Handler, + return &websocketWorker{ + client: client, + registrationRequest: opts.RegistrationRequest, + handler: opts.Handler, + } } } diff --git a/nitric/workers/manager.go b/nitric/workers/manager.go index 594e0b3..c354c9a 100644 --- a/nitric/workers/manager.go +++ b/nitric/workers/manager.go @@ -23,9 +23,8 @@ import ( "sync" multierror "github.com/missionMeteora/toolkit/errors" - "google.golang.org/grpc" - "github.com/nitrictech/go-sdk/constants" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" apierrors "github.com/nitrictech/go-sdk/nitric/errors" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" ) @@ -36,9 +35,7 @@ type RegisterResult struct { } type Manager struct { - workers map[string]StreamWorker - conn grpc.ClientConnInterface - connMutex sync.Mutex + workers map[string]StreamWorker rsc v1.ResourcesClient } @@ -62,23 +59,8 @@ func (m *Manager) AddWorker(name string, s StreamWorker) { m.workers[name] = s } -func (m *Manager) GetConnection() (grpc.ClientConnInterface, error) { - m.connMutex.Lock() - defer m.connMutex.Unlock() - - if m.conn == nil { - conn, err := grpc.NewClient(constants.NitricAddress(), constants.DefaultOptions()...) - if err != nil { - return nil, err - } - m.conn = conn - } - - return m.conn, nil -} - func (m *Manager) resourceServiceClient() (v1.ResourcesClient, error) { - conn, err := m.GetConnection() + conn, err := grpcx.GetConnection() if err != nil { return nil, err } From 29da8e7b6052895a9e7ee93dfbe26d4a991f9229 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 1 Oct 2024 16:10:09 +1000 Subject: [PATCH 29/42] fix tests --- nitric/websockets/websocket.go | 3 ++- nitric/websockets/websocket_workers.go | 32 ++++++++++++-------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/nitric/websockets/websocket.go b/nitric/websockets/websocket.go index 691e2ae..aa1e30e 100644 --- a/nitric/websockets/websocket.go +++ b/nitric/websockets/websocket.go @@ -18,6 +18,7 @@ import ( "context" "strings" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/handlers" "github.com/nitrictech/go-sdk/nitric/workers" resourcesv1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" @@ -72,7 +73,7 @@ func NewWebsocket(name string) (Websocket, error) { return nil, err } - conn, err := manager.GetConnection() + conn, err := grpcx.GetConnection() if err != nil { return nil, err } diff --git a/nitric/websockets/websocket_workers.go b/nitric/websockets/websocket_workers.go index 31deede..3e9736a 100644 --- a/nitric/websockets/websocket_workers.go +++ b/nitric/websockets/websocket_workers.go @@ -19,10 +19,10 @@ import ( errorsstd "errors" "io" + grpcx "github.com/nitrictech/go-sdk/internal/grpc" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" "github.com/nitrictech/go-sdk/nitric/handlers" - "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) @@ -85,23 +85,21 @@ func (w *websocketWorker) Start(ctx context.Context) error { } } -func newWebsocketWorker(opts *websocketWorkerOpts) func(m *workers.Manager) *websocketWorker { - return func(m *workers.Manager) *websocketWorker { - conn, err := m.GetConnection() - if err != nil { - panic(errors.NewWithCause( - codes.Unavailable, - "NewWebsocketWorker: Unable to reach WebsocketHandlerClient", - err, - )) - } +func newWebsocketWorker(opts *websocketWorkerOpts) *websocketWorker { + conn, err := grpcx.GetConnection() + if err != nil { + panic(errors.NewWithCause( + codes.Unavailable, + "NewWebsocketWorker: Unable to reach WebsocketHandlerClient", + err, + )) + } - client := v1.NewWebsocketHandlerClient(conn) + client := v1.NewWebsocketHandlerClient(conn) - return &websocketWorker{ - client: client, - registrationRequest: opts.RegistrationRequest, - handler: opts.Handler, - } + return &websocketWorker{ + client: client, + registrationRequest: opts.RegistrationRequest, + handler: opts.Handler, } } From fb9ea1562323e3a84c4720c6661da0af8a254000 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Tue, 1 Oct 2024 16:55:53 +1000 Subject: [PATCH 30/42] readd missing run func --- nitric/nitric.go | 5 +++++ nitric/workers/manager.go | 7 +------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nitric/nitric.go b/nitric/nitric.go index 0a44b11..a377ad4 100644 --- a/nitric/nitric.go +++ b/nitric/nitric.go @@ -24,6 +24,7 @@ import ( "github.com/nitrictech/go-sdk/nitric/storage" "github.com/nitrictech/go-sdk/nitric/topics" "github.com/nitrictech/go-sdk/nitric/websockets" + "github.com/nitrictech/go-sdk/nitric/workers" ) var NewApi = apis.NewApi @@ -35,3 +36,7 @@ var NewSqlDatabase = sql.NewSqlDatabase var NewBucket = storage.NewBucket var NewTopic = topics.NewTopic var NewWebsocket = websockets.NewWebsocket + +func Run() error { + return workers.GetDefaultManager().Run() +} diff --git a/nitric/workers/manager.go b/nitric/workers/manager.go index c354c9a..3a55d33 100644 --- a/nitric/workers/manager.go +++ b/nitric/workers/manager.go @@ -137,12 +137,7 @@ func (m *Manager) RegisterPolicy(res *v1.ResourceIdentifier, actions ...v1.Actio return nil } -// Run will run the service and callback the required handlers when events are received. -func Run() error { - return defaultManager.run() -} - -func (m *Manager) run() error { +func (m *Manager) Run() error { wg := sync.WaitGroup{} errList := &multierror.ErrorList{} From 26f60543b904573ffe55ca1bf3328494ad816028 Mon Sep 17 00:00:00 2001 From: Ryan Cartwright Date: Tue, 1 Oct 2024 17:17:27 +1000 Subject: [PATCH 31/42] add missing license headers --- internal/grpc/grpcx.go | 14 ++++++++++++++ nitric/apis/options.go | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/internal/grpc/grpcx.go b/internal/grpc/grpcx.go index 4cf4cb7..b08ccb9 100644 --- a/internal/grpc/grpcx.go +++ b/internal/grpc/grpcx.go @@ -1,3 +1,17 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 grpcx import ( diff --git a/nitric/apis/options.go b/nitric/apis/options.go index 27abb57..b239d88 100644 --- a/nitric/apis/options.go +++ b/nitric/apis/options.go @@ -1,3 +1,17 @@ +// Copyright 2021 Nitric Technologies Pty Ltd. +// +// 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 apis type ( From b6901a0064a4092baf023f73833f075874460268 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 2 Oct 2024 11:30:32 +1000 Subject: [PATCH 32/42] Add missing conversion case. --- nitric/handlers/handlers.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nitric/handlers/handlers.go b/nitric/handlers/handlers.go index 13d2a25..a0374ec 100644 --- a/nitric/handlers/handlers.go +++ b/nitric/handlers/handlers.go @@ -48,6 +48,8 @@ func HandlerFromInterface[T any](handler interface{}) (Handler[T], error) { handlerType(ctx) return nil } + case func(*T) error: + handlerType = Handler[T](handlerType) case Handler[T]: typedHandler = handlerType From 9439b7fb5905d910a751c950194a20d570c83da1 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 2 Oct 2024 11:31:46 +1000 Subject: [PATCH 33/42] fix typo and cleanup comments. --- nitric/handlers/handlers.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nitric/handlers/handlers.go b/nitric/handlers/handlers.go index a0374ec..0f8d354 100644 --- a/nitric/handlers/handlers.go +++ b/nitric/handlers/handlers.go @@ -27,8 +27,6 @@ type ( // func() error // func(*T) // func(*T) error -// func(*T) *T -// func(*T) (*T, error) // Handler[T] // If the function is not a valid type, an error is returned func HandlerFromInterface[T any](handler interface{}) (Handler[T], error) { @@ -49,7 +47,7 @@ func HandlerFromInterface[T any](handler interface{}) (Handler[T], error) { return nil } case func(*T) error: - handlerType = Handler[T](handlerType) + typedHandler = Handler[T](handlerType) case Handler[T]: typedHandler = handlerType From 332ca96658c46beba62a4ddc59b27e6e6b87f762 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 2 Oct 2024 11:49:51 +1000 Subject: [PATCH 34/42] update options to types over aliases --- internal/grpc/grpcx.go | 3 ++- nitric/apis/api.go | 10 +++++----- nitric/apis/options.go | 8 ++++---- nitric/handlers/handlers.go | 1 - nitric/nitric.go | 20 +++++++++++--------- nitric/topics/client.go | 2 +- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/internal/grpc/grpcx.go b/internal/grpc/grpcx.go index b08ccb9..97b7976 100644 --- a/internal/grpc/grpcx.go +++ b/internal/grpc/grpcx.go @@ -17,8 +17,9 @@ package grpcx import ( "sync" - "github.com/nitrictech/go-sdk/constants" "google.golang.org/grpc" + + "github.com/nitrictech/go-sdk/constants" ) type grpcManager struct { diff --git a/nitric/apis/api.go b/nitric/apis/api.go index b47e149..c2d2dd7 100644 --- a/nitric/apis/api.go +++ b/nitric/apis/api.go @@ -19,7 +19,7 @@ import ( "path" "strings" - . "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/nitric/handlers" resources "github.com/nitrictech/go-sdk/nitric/resource" "github.com/nitrictech/go-sdk/nitric/workers" resourcev1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" @@ -47,13 +47,13 @@ type Route interface { ApiName() string } -type ApiMiddleware = Middleware[Ctx] +type Middleware = handlers.Middleware[Ctx] type route struct { path string api *api manager *workers.Manager - middleware ApiMiddleware + middleware Middleware } func (a *api) NewRoute(match string, opts ...RouteOption) Route { @@ -90,7 +90,7 @@ func (r *route) AddMethodHandler(methods []string, handler interface{}, opts ... o(mo) } - typedHandler, err := HandlerFromInterface[Ctx](handler) + typedHandler, err := handlers.HandlerFromInterface[Ctx](handler) if err != nil { panic(err) } @@ -242,7 +242,7 @@ type api struct { securityRules map[string]interface{} security []OidcOptions path string - middleware ApiMiddleware + middleware Middleware } // Get adds a Get method handler to the path with any specified opts. diff --git a/nitric/apis/options.go b/nitric/apis/options.go index b239d88..1c8fcbe 100644 --- a/nitric/apis/options.go +++ b/nitric/apis/options.go @@ -15,9 +15,9 @@ package apis type ( - ApiOption = func(api *api) - RouteOption = func(route Route) - MethodOption = func(mo *methodOptions) + ApiOption func(api *api) + RouteOption func(route Route) + MethodOption func(mo *methodOptions) ) type JwtSecurityRule struct { @@ -30,7 +30,7 @@ type methodOptions struct { securityDisabled bool } -func WithMiddleware(middleware ApiMiddleware) ApiOption { +func WithMiddleware(middleware Middleware) ApiOption { return func(api *api) { api.middleware = middleware } diff --git a/nitric/handlers/handlers.go b/nitric/handlers/handlers.go index 0f8d354..014a25b 100644 --- a/nitric/handlers/handlers.go +++ b/nitric/handlers/handlers.go @@ -50,7 +50,6 @@ func HandlerFromInterface[T any](handler interface{}) (Handler[T], error) { typedHandler = Handler[T](handlerType) case Handler[T]: typedHandler = handlerType - default: return nil, fmt.Errorf("invalid handler type: %T", handler) } diff --git a/nitric/nitric.go b/nitric/nitric.go index a377ad4..8fa88b0 100644 --- a/nitric/nitric.go +++ b/nitric/nitric.go @@ -27,15 +27,17 @@ import ( "github.com/nitrictech/go-sdk/nitric/workers" ) -var NewApi = apis.NewApi -var NewKv = keyvalue.NewKv -var NewQueue = queues.NewQueue -var NewSchedule = schedules.NewSchedule -var NewSecret = secrets.NewSecret -var NewSqlDatabase = sql.NewSqlDatabase -var NewBucket = storage.NewBucket -var NewTopic = topics.NewTopic -var NewWebsocket = websockets.NewWebsocket +var ( + NewApi = apis.NewApi + NewKv = keyvalue.NewKv + NewQueue = queues.NewQueue + NewSchedule = schedules.NewSchedule + NewSecret = secrets.NewSecret + NewSqlDatabase = sql.NewSqlDatabase + NewBucket = storage.NewBucket + NewTopic = topics.NewTopic + NewWebsocket = websockets.NewWebsocket +) func Run() error { return workers.GetDefaultManager().Run() diff --git a/nitric/topics/client.go b/nitric/topics/client.go index 63aa4bb..09c63a2 100644 --- a/nitric/topics/client.go +++ b/nitric/topics/client.go @@ -27,7 +27,7 @@ import ( "github.com/nitrictech/protoutils" ) -type PublishOption = func(*v1.TopicPublishRequest) +type PublishOption func(*v1.TopicPublishRequest) // TopicClientIface for pub/sub async messaging. type TopicClientIface interface { From 83c2c9ebc548341a0df5debe3c0b45ed1e504e13 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 2 Oct 2024 11:56:06 +1000 Subject: [PATCH 35/42] remove out of date comments. --- nitric/apis/api.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/nitric/apis/api.go b/nitric/apis/api.go index c2d2dd7..b825506 100644 --- a/nitric/apis/api.go +++ b/nitric/apis/api.go @@ -169,8 +169,6 @@ func (r *route) Options(handler interface{}, opts ...MethodOption) { // Api Resource represents an HTTP API, capable of routing and securing incoming HTTP requests to handlers. // path is the route path matcher e.g. '/home'. Supports path params via colon prefix e.g. '/customers/:customerId' // handler the handler to register for callbacks. -// -// Note: to chain handler use handler.ComposeHttpMiddlware() type Api interface { // Get adds a Get method handler to the path with any specified opts. // Valid function signatures: @@ -246,7 +244,6 @@ type api struct { } // Get adds a Get method handler to the path with any specified opts. -// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Get(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -255,7 +252,6 @@ func (a *api) Get(match string, handler interface{}, opts ...MethodOption) { } // Post adds a Post method handler to the path with any specified opts. -// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Post(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -264,7 +260,6 @@ func (a *api) Post(match string, handler interface{}, opts ...MethodOption) { } // Patch adds a Patch method handler to the path with any specified opts. -// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Patch(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -273,7 +268,6 @@ func (a *api) Patch(match string, handler interface{}, opts ...MethodOption) { } // Put adds a Put method handler to the path with any specified opts. -// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Put(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -282,7 +276,6 @@ func (a *api) Put(match string, handler interface{}, opts ...MethodOption) { } // Delete adds a Delete method handler to the path with any specified opts. -// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Delete(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) @@ -291,7 +284,6 @@ func (a *api) Delete(match string, handler interface{}, opts ...MethodOption) { } // Options adds an Options method handler to the path with any specified opts. -// Note: to chain handler use handler.ComposeHttpMiddlware() func (a *api) Options(match string, handler interface{}, opts ...MethodOption) { r := a.NewRoute(match) From 9e0c593807eaf81b43c2067f1dbea40dbc5798dc Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 2 Oct 2024 12:14:43 +1000 Subject: [PATCH 36/42] make the handlers package internal --- {nitric => internal}/handlers/handlers.go | 0 {nitric => internal}/handlers/handlers_test.go | 0 nitric/apis/api.go | 3 ++- nitric/apis/workers.go | 2 +- nitric/schedules/schedule.go | 2 +- nitric/schedules/schedule_workers.go | 2 +- nitric/storage/bucket.go | 2 +- nitric/storage/bucket_workers.go | 2 +- nitric/topics/topic.go | 2 +- nitric/topics/topic_workers.go | 2 +- nitric/websockets/websocket.go | 2 +- nitric/websockets/websocket_workers.go | 2 +- 12 files changed, 11 insertions(+), 10 deletions(-) rename {nitric => internal}/handlers/handlers.go (100%) rename {nitric => internal}/handlers/handlers_test.go (100%) diff --git a/nitric/handlers/handlers.go b/internal/handlers/handlers.go similarity index 100% rename from nitric/handlers/handlers.go rename to internal/handlers/handlers.go diff --git a/nitric/handlers/handlers_test.go b/internal/handlers/handlers_test.go similarity index 100% rename from nitric/handlers/handlers_test.go rename to internal/handlers/handlers_test.go diff --git a/nitric/apis/api.go b/nitric/apis/api.go index b825506..3552278 100644 --- a/nitric/apis/api.go +++ b/nitric/apis/api.go @@ -19,7 +19,7 @@ import ( "path" "strings" - "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/internal/handlers" resources "github.com/nitrictech/go-sdk/nitric/resource" "github.com/nitrictech/go-sdk/nitric/workers" resourcev1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" @@ -47,6 +47,7 @@ type Route interface { ApiName() string } +type Handler = handlers.Handler[Ctx] type Middleware = handlers.Middleware[Ctx] type route struct { diff --git a/nitric/apis/workers.go b/nitric/apis/workers.go index 7a7df9d..0305b98 100644 --- a/nitric/apis/workers.go +++ b/nitric/apis/workers.go @@ -20,9 +20,9 @@ import ( "io" grpcx "github.com/nitrictech/go-sdk/internal/grpc" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/handlers" "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" ) diff --git a/nitric/schedules/schedule.go b/nitric/schedules/schedule.go index 586bd0d..d0bde6f 100644 --- a/nitric/schedules/schedule.go +++ b/nitric/schedules/schedule.go @@ -17,7 +17,7 @@ package schedules import ( "strings" - "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/workers" schedulespb "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) diff --git a/nitric/schedules/schedule_workers.go b/nitric/schedules/schedule_workers.go index 9959806..d94fa68 100644 --- a/nitric/schedules/schedule_workers.go +++ b/nitric/schedules/schedule_workers.go @@ -20,9 +20,9 @@ import ( "io" grpcx "github.com/nitrictech/go-sdk/internal/grpc" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/schedules/v1" ) diff --git a/nitric/storage/bucket.go b/nitric/storage/bucket.go index 08ddb88..41ff8e0 100644 --- a/nitric/storage/bucket.go +++ b/nitric/storage/bucket.go @@ -18,7 +18,7 @@ import ( "fmt" "strings" - "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" storagepb "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" diff --git a/nitric/storage/bucket_workers.go b/nitric/storage/bucket_workers.go index 6f817d2..6e1ba2e 100644 --- a/nitric/storage/bucket_workers.go +++ b/nitric/storage/bucket_workers.go @@ -20,9 +20,9 @@ import ( "io" grpcx "github.com/nitrictech/go-sdk/internal/grpc" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/storage/v1" ) diff --git a/nitric/topics/topic.go b/nitric/topics/topic.go index 65ddca0..f6e15b4 100644 --- a/nitric/topics/topic.go +++ b/nitric/topics/topic.go @@ -17,7 +17,7 @@ package topics import ( "fmt" - "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/workers" v1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" topicspb "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" diff --git a/nitric/topics/topic_workers.go b/nitric/topics/topic_workers.go index af00678..7d6b7a1 100644 --- a/nitric/topics/topic_workers.go +++ b/nitric/topics/topic_workers.go @@ -21,9 +21,9 @@ import ( errorsstd "errors" grpcx "github.com/nitrictech/go-sdk/internal/grpc" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/topics/v1" ) diff --git a/nitric/websockets/websocket.go b/nitric/websockets/websocket.go index aa1e30e..c5fe000 100644 --- a/nitric/websockets/websocket.go +++ b/nitric/websockets/websocket.go @@ -19,7 +19,7 @@ import ( "strings" grpcx "github.com/nitrictech/go-sdk/internal/grpc" - "github.com/nitrictech/go-sdk/nitric/handlers" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/workers" resourcesv1 "github.com/nitrictech/nitric/core/pkg/proto/resources/v1" websocketsv1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" diff --git a/nitric/websockets/websocket_workers.go b/nitric/websockets/websocket_workers.go index 3e9736a..e0aafb9 100644 --- a/nitric/websockets/websocket_workers.go +++ b/nitric/websockets/websocket_workers.go @@ -20,9 +20,9 @@ import ( "io" grpcx "github.com/nitrictech/go-sdk/internal/grpc" + "github.com/nitrictech/go-sdk/internal/handlers" "github.com/nitrictech/go-sdk/nitric/errors" "github.com/nitrictech/go-sdk/nitric/errors/codes" - "github.com/nitrictech/go-sdk/nitric/handlers" v1 "github.com/nitrictech/nitric/core/pkg/proto/websockets/v1" ) From 655475be987f52edd71e86b73be6bfcc6b602bc8 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 2 Oct 2024 12:36:01 +1000 Subject: [PATCH 37/42] use MIMEHeader for http request headers --- nitric/apis/context.go | 8 ++++++-- nitric/apis/request.go | 8 +++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/nitric/apis/context.go b/nitric/apis/context.go index de0d499..b9a3c7f 100644 --- a/nitric/apis/context.go +++ b/nitric/apis/context.go @@ -14,7 +14,11 @@ package apis -import apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" +import ( + "net/textproto" + + apispb "github.com/nitrictech/nitric/core/pkg/proto/apis/v1" +) type Ctx struct { id string @@ -46,7 +50,7 @@ func (c *Ctx) ToClientMessage() *apispb.ClientMessage { func NewCtx(msg *apispb.ServerMessage) *Ctx { req := msg.GetHttpRequest() - headers := make(map[string][]string) + headers := make(textproto.MIMEHeader) for k, v := range req.Headers { headers[k] = v.GetValue() } diff --git a/nitric/apis/request.go b/nitric/apis/request.go index 5d3f458..b69b87d 100644 --- a/nitric/apis/request.go +++ b/nitric/apis/request.go @@ -14,12 +14,14 @@ package apis +import "net/textproto" + type Request interface { Method() string Path() string Data() []byte Query() map[string][]string - Headers() map[string][]string + Headers() textproto.MIMEHeader PathParams() map[string]string } @@ -28,7 +30,7 @@ type HttpRequest struct { path string data []byte query map[string][]string - headers map[string][]string + headers textproto.MIMEHeader pathParams map[string]string } @@ -48,7 +50,7 @@ func (h *HttpRequest) Query() map[string][]string { return h.query } -func (h *HttpRequest) Headers() map[string][]string { +func (h *HttpRequest) Headers() textproto.MIMEHeader { return h.headers } From c10b43ff0046e9fe14d6723e605d58db9e5a7711 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 2 Oct 2024 13:00:56 +1000 Subject: [PATCH 38/42] panic on resource creation failure --- nitric/apis/api.go | 8 ++++---- nitric/sql/sql.go | 9 +++++++-- nitric/websockets/websocket.go | 10 +++++----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/nitric/apis/api.go b/nitric/apis/api.go index 3552278..1f2b381 100644 --- a/nitric/apis/api.go +++ b/nitric/apis/api.go @@ -295,7 +295,7 @@ func (a *api) Options(match string, handler interface{}, opts ...MethodOption) { // NewApi Registers a new API Resource. // // The returned API object can be used to register Routes and Methods, with Handlers. -func NewApi(name string, opts ...ApiOption) (Api, error) { +func NewApi(name string, opts ...ApiOption) Api { a := &api{ name: name, routes: map[string]Route{}, @@ -314,7 +314,7 @@ func NewApi(name string, opts ...ApiOption) (Api, error) { for _, oidcOption := range a.security { err := attachOidc(a.name, oidcOption, a.manager) if err != nil { - return nil, err + panic(err) } if apiResource.GetSecurity() == nil { @@ -336,8 +336,8 @@ func NewApi(name string, opts ...ApiOption) (Api, error) { }, }) if result.Err != nil { - return nil, result.Err + panic(result.Err) } - return a, nil + return a } diff --git a/nitric/sql/sql.go b/nitric/sql/sql.go index adc7d8a..d8e69aa 100644 --- a/nitric/sql/sql.go +++ b/nitric/sql/sql.go @@ -32,7 +32,7 @@ func WithMigrationsPath(path string) sqlDatabaseOption { } // NewSqlDatabase - Create a new Sql Database resource -func NewSqlDatabase(name string, opts ...sqlDatabaseOption) (*SqlClient, error) { +func NewSqlDatabase(name string, opts ...sqlDatabaseOption) *SqlClient { resourceConfig := &v1.ResourceDeclareRequest_SqlDatabase{ SqlDatabase: &v1.SqlDatabaseResource{}, } @@ -55,5 +55,10 @@ func NewSqlDatabase(name string, opts ...sqlDatabaseOption) (*SqlClient, error) <-registerChan }() - return NewSqlClient(name) + client, err := NewSqlClient(name) + if err != nil { + panic(err) + } + + return client } diff --git a/nitric/websockets/websocket.go b/nitric/websockets/websocket.go index c5fe000..4c462fa 100644 --- a/nitric/websockets/websocket.go +++ b/nitric/websockets/websocket.go @@ -53,7 +53,7 @@ type websocket struct { } // NewWebsocket - Create a new Websocket API resource -func NewWebsocket(name string) (Websocket, error) { +func NewWebsocket(name string) Websocket { manager := workers.GetDefaultManager() registerResult := <-manager.RegisterResource(&resourcesv1.ResourceDeclareRequest{ @@ -63,19 +63,19 @@ func NewWebsocket(name string) (Websocket, error) { }, }) if registerResult.Err != nil { - return nil, registerResult.Err + panic(registerResult.Err) } actions := []resourcesv1.Action{resourcesv1.Action_WebsocketManage} err := manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return nil, err + panic(err) } conn, err := grpcx.GetConnection() if err != nil { - return nil, err + panic(err) } wClient := websocketsv1.NewWebsocketClient(conn) @@ -84,7 +84,7 @@ func NewWebsocket(name string) (Websocket, error) { manager: manager, client: wClient, name: name, - }, nil + } } func (w *websocket) Name() string { From 093f19f1275a487c63c129ef2c5da667705b3ca5 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 2 Oct 2024 13:24:17 +1000 Subject: [PATCH 39/42] panic on permission request failures --- nitric/keyvalue/keyvalue.go | 17 +++++++++++------ nitric/queues/queue.go | 17 +++++++++++------ nitric/secrets/secret.go | 17 +++++++++++------ nitric/storage/bucket.go | 17 +++++++++++------ nitric/topics/topic.go | 17 +++++++++++------ 5 files changed, 55 insertions(+), 30 deletions(-) diff --git a/nitric/keyvalue/keyvalue.go b/nitric/keyvalue/keyvalue.go index 3ed5f0c..846dc5e 100644 --- a/nitric/keyvalue/keyvalue.go +++ b/nitric/keyvalue/keyvalue.go @@ -33,7 +33,7 @@ var KvStoreEverything []KvStorePermission = []KvStorePermission{KvStoreSet, KvSt type KvStore interface { // Allow requests the given permissions to the key/value store. - Allow(KvStorePermission, ...KvStorePermission) (KvStoreClientIface, error) + Allow(KvStorePermission, ...KvStorePermission) KvStoreClientIface } type kvstore struct { @@ -63,7 +63,7 @@ func NewKv(name string) *kvstore { return kvstore } -func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePermission) (KvStoreClientIface, error) { +func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePermission) KvStoreClientIface { allPerms := append([]KvStorePermission{permission}, permissions...) actions := []v1.Action{} @@ -76,20 +76,25 @@ func (k *kvstore) Allow(permission KvStorePermission, permissions ...KvStorePerm case KvStoreDelete: actions = append(actions, v1.Action_KeyValueStoreDelete) default: - return nil, fmt.Errorf("KvStorePermission %s unknown", perm) + panic(fmt.Sprintf("KvStorePermission %s unknown", perm)) } } registerResult := <-k.registerChan if registerResult.Err != nil { - return nil, registerResult.Err + panic(registerResult.Err) } err := k.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return nil, err + panic(err) } - return NewKvStoreClient(k.name) + client, err := NewKvStoreClient(k.name) + if err != nil { + panic(err) + } + + return client } diff --git a/nitric/queues/queue.go b/nitric/queues/queue.go index d380b95..3dc5acf 100644 --- a/nitric/queues/queue.go +++ b/nitric/queues/queue.go @@ -32,7 +32,7 @@ var QueueEverything []QueuePermission = []QueuePermission{QueueEnqueue, QueueDeq type Queue interface { // Allow requests the given permissions to the queue. - Allow(QueuePermission, ...QueuePermission) (*QueueClient, error) + Allow(QueuePermission, ...QueuePermission) *QueueClient } type queue struct { @@ -62,7 +62,7 @@ func NewQueue(name string) *queue { return queue } -func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission) (*QueueClient, error) { +func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission) *QueueClient { allPerms := append([]QueuePermission{permission}, permissions...) actions := []v1.Action{} @@ -73,19 +73,24 @@ func (q *queue) Allow(permission QueuePermission, permissions ...QueuePermission case QueueEnqueue: actions = append(actions, v1.Action_QueueEnqueue) default: - return nil, fmt.Errorf("QueuePermission %s unknown", perm) + panic(fmt.Sprintf("QueuePermission %s unknown", perm)) } } registerResult := <-q.registerChan if registerResult.Err != nil { - return nil, registerResult.Err + panic(registerResult.Err) } err := q.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return nil, err + panic(err) } - return NewQueueClient(q.name) + client, err := NewQueueClient(q.name) + if err != nil { + panic(err) + } + + return client } diff --git a/nitric/secrets/secret.go b/nitric/secrets/secret.go index db4f953..ece6d15 100644 --- a/nitric/secrets/secret.go +++ b/nitric/secrets/secret.go @@ -32,7 +32,7 @@ var SecretEverything []SecretPermission = []SecretPermission{SecretAccess, Secre type Secret interface { // Allow requests the given permissions to the secret. - Allow(SecretPermission, ...SecretPermission) (*SecretClient, error) + Allow(SecretPermission, ...SecretPermission) *SecretClient } type secret struct { @@ -61,7 +61,7 @@ func NewSecret(name string) *secret { return secret } -func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermission) (*SecretClient, error) { +func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermission) *SecretClient { allPerms := append([]SecretPermission{permission}, permissions...) actions := []v1.Action{} @@ -72,19 +72,24 @@ func (s *secret) Allow(permission SecretPermission, permissions ...SecretPermiss case SecretPut: actions = append(actions, v1.Action_SecretPut) default: - return nil, fmt.Errorf("secretPermission %s unknown", perm) + panic(fmt.Sprintf("secretPermission %s unknown", perm)) } } registerResult := <-s.registerChan if registerResult.Err != nil { - return nil, registerResult.Err + panic(registerResult.Err) } err := s.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return nil, err + panic(err) } - return NewSecretClient(s.name) + client, err := NewSecretClient(s.name) + if err != nil { + panic(err) + } + + return client } diff --git a/nitric/storage/bucket.go b/nitric/storage/bucket.go index 41ff8e0..04304fe 100644 --- a/nitric/storage/bucket.go +++ b/nitric/storage/bucket.go @@ -34,7 +34,7 @@ type bucket struct { type Bucket interface { // Allow requests the given permissions to the bucket. - Allow(BucketPermission, ...BucketPermission) (*BucketClient, error) + Allow(BucketPermission, ...BucketPermission) *BucketClient // On registers a handler for a specific event type on the bucket. // Valid function signatures for handler are: @@ -75,7 +75,7 @@ func NewBucket(name string) Bucket { return bucket } -func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) (*BucketClient, error) { +func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermission) *BucketClient { allPerms := append([]BucketPermission{permission}, permissions...) actions := []v1.Action{} @@ -88,21 +88,26 @@ func (b *bucket) Allow(permission BucketPermission, permissions ...BucketPermiss case BucketDelete: actions = append(actions, v1.Action_BucketFileDelete) default: - return nil, fmt.Errorf("bucketPermission %s unknown", perm) + panic(fmt.Sprintf("bucketPermission %s unknown", perm)) } } registerResult := <-b.registerChan if registerResult.Err != nil { - return nil, registerResult.Err + panic(registerResult.Err) } err := b.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return nil, err + panic(err) + } + + client, err := NewBucketClient(b.name) + if err != nil { + panic(err) } - return NewBucketClient(b.name) + return client } func (b *bucket) On(eventType EventType, notificationPrefixFilter string, handler interface{}) { diff --git a/nitric/topics/topic.go b/nitric/topics/topic.go index f6e15b4..5cd4314 100644 --- a/nitric/topics/topic.go +++ b/nitric/topics/topic.go @@ -33,7 +33,7 @@ const ( type SubscribableTopic interface { // Allow requests the given permissions to the topic. - Allow(TopicPermission, ...TopicPermission) (*TopicClient, error) + Allow(TopicPermission, ...TopicPermission) *TopicClient // Subscribe will register and start a subscription handler that will be called for all events from this topic. // Valid function signatures for handler are: @@ -72,7 +72,7 @@ func NewTopic(name string) SubscribableTopic { return topic } -func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...TopicPermission) (*TopicClient, error) { +func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...TopicPermission) *TopicClient { allPerms := append([]TopicPermission{permission}, permissions...) actions := []v1.Action{} @@ -81,21 +81,26 @@ func (t *subscribableTopic) Allow(permission TopicPermission, permissions ...Top case TopicPublish: actions = append(actions, v1.Action_TopicPublish) default: - return nil, fmt.Errorf("TopicPermission %s unknown", perm) + panic(fmt.Sprintf("TopicPermission %s unknown", perm)) } } registerResult := <-t.registerChan if registerResult.Err != nil { - return nil, registerResult.Err + panic(registerResult.Err) } err := t.manager.RegisterPolicy(registerResult.Identifier, actions...) if err != nil { - return nil, err + panic(err) + } + + client, err := NewTopicClient(t.name) + if err != nil { + panic(err) } - return NewTopicClient(t.name) + return client } func (t *subscribableTopic) Subscribe(handler interface{}) { From 7b248747d42ba955e6a73a94bcb333a584d1b6f2 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 2 Oct 2024 13:29:28 +1000 Subject: [PATCH 40/42] panic if run fails --- nitric/nitric.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nitric/nitric.go b/nitric/nitric.go index 8fa88b0..d2d5f53 100644 --- a/nitric/nitric.go +++ b/nitric/nitric.go @@ -39,6 +39,9 @@ var ( NewWebsocket = websockets.NewWebsocket ) -func Run() error { - return workers.GetDefaultManager().Run() +func Run() { + err := workers.GetDefaultManager().Run() + if err != nil { + panic(err) + } } From 7b4d262fe3e03fed370f0fb3b362805a749e3fea Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 2 Oct 2024 13:37:54 +1000 Subject: [PATCH 41/42] document api options --- nitric/apis/options.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nitric/apis/options.go b/nitric/apis/options.go index 1c8fcbe..bbaf790 100644 --- a/nitric/apis/options.go +++ b/nitric/apis/options.go @@ -30,6 +30,7 @@ type methodOptions struct { securityDisabled bool } +// WithMiddleware - Apply a middleware function to all handlers in the API func WithMiddleware(middleware Middleware) ApiOption { return func(api *api) { api.middleware = middleware @@ -47,6 +48,7 @@ func OidcRule(name string, issuer string, audiences []string) SecurityOption { } } +// WithSecurityJwtRule - Apply a JWT security rule to the API func WithSecurityJwtRule(name string, rule JwtSecurityRule) ApiOption { return func(api *api) { if api.securityRules == nil { @@ -57,6 +59,7 @@ func WithSecurityJwtRule(name string, rule JwtSecurityRule) ApiOption { } } +// WithSecurity - Apply security settings to the API func WithSecurity(oidcOptions OidcOptions) ApiOption { return func(api *api) { if api.security == nil { @@ -67,18 +70,21 @@ func WithSecurity(oidcOptions OidcOptions) ApiOption { } } +// WithPath - Set the base path for the API func WithPath(path string) ApiOption { return func(api *api) { api.path = path } } +// WithNoMethodSecurity - Disable security for a method func WithNoMethodSecurity() MethodOption { return func(mo *methodOptions) { mo.securityDisabled = true } } +// WithMethodSecurity - Override/set the security settings for a method func WithMethodSecurity(oidcOptions OidcOptions) MethodOption { return func(mo *methodOptions) { mo.securityDisabled = false From afe48a0f8e6191e21617b6e2040106ace71270fd Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 2 Oct 2024 14:18:16 +1000 Subject: [PATCH 42/42] add missing iface method param names --- nitric/keyvalue/client.go | 8 ++++---- nitric/keyvalue/keyvalue.go | 2 +- nitric/queues/client.go | 4 ++-- nitric/queues/queue.go | 2 +- nitric/secrets/client.go | 10 +++++----- nitric/secrets/secret.go | 2 +- nitric/sql/client.go | 2 +- nitric/storage/bucket.go | 2 +- nitric/topics/client.go | 2 +- nitric/topics/topic.go | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/nitric/keyvalue/client.go b/nitric/keyvalue/client.go index 4e0d714..f688f18 100644 --- a/nitric/keyvalue/client.go +++ b/nitric/keyvalue/client.go @@ -54,13 +54,13 @@ type KvStoreClientIface interface { // Name - The name of the store Name() string // Get a value from the store - Get(context.Context, string) (map[string]interface{}, error) + Get(ctx context.Context, key string) (map[string]interface{}, error) // Set a value in the store - Set(context.Context, string, map[string]interface{}) error + Set(ctx context.Context, key string, value map[string]interface{}) error // Delete a value from the store - Delete(context.Context, string) error + Delete(ctx context.Context, key string) error // Return an async iterable of keys in the store - Keys(context.Context, ...ScanKeysOption) (*KeyStream, error) + Keys(ctx context.Context, options ...ScanKeysOption) (*KeyStream, error) } type KvStoreClient struct { diff --git a/nitric/keyvalue/keyvalue.go b/nitric/keyvalue/keyvalue.go index 846dc5e..0eb9fe6 100644 --- a/nitric/keyvalue/keyvalue.go +++ b/nitric/keyvalue/keyvalue.go @@ -33,7 +33,7 @@ var KvStoreEverything []KvStorePermission = []KvStorePermission{KvStoreSet, KvSt type KvStore interface { // Allow requests the given permissions to the key/value store. - Allow(KvStorePermission, ...KvStorePermission) KvStoreClientIface + Allow(permission KvStorePermission, permissions ...KvStorePermission) KvStoreClientIface } type kvstore struct { diff --git a/nitric/queues/client.go b/nitric/queues/client.go index 4cf404d..023e7db 100644 --- a/nitric/queues/client.go +++ b/nitric/queues/client.go @@ -28,9 +28,9 @@ type QueueClientIface interface { // Name - The name of the queue Name() string // Enqueue - Push a number of messages to a queue - Enqueue(context.Context, []map[string]interface{}) ([]*FailedMessage, error) + Enqueue(ctx context.Context, messages []map[string]interface{}) ([]*FailedMessage, error) // Dequeue - Retrieve messages from a queue to a maximum of the given depth - Dequeue(context.Context, int) ([]ReceivedMessage, error) + Dequeue(ctx context.Context, depth int) ([]ReceivedMessage, error) } type QueueClient struct { diff --git a/nitric/queues/queue.go b/nitric/queues/queue.go index 3dc5acf..2b8c62a 100644 --- a/nitric/queues/queue.go +++ b/nitric/queues/queue.go @@ -32,7 +32,7 @@ var QueueEverything []QueuePermission = []QueuePermission{QueueEnqueue, QueueDeq type Queue interface { // Allow requests the given permissions to the queue. - Allow(QueuePermission, ...QueuePermission) *QueueClient + Allow(permission QueuePermission, permissions ...QueuePermission) *QueueClient } type queue struct { diff --git a/nitric/secrets/client.go b/nitric/secrets/client.go index 5f43b23..6c72866 100644 --- a/nitric/secrets/client.go +++ b/nitric/secrets/client.go @@ -33,11 +33,11 @@ type SecretClientIface interface { // Name - Return the name of this secret Name() string // Put - Store a new value in this secret, returning a reference to the new version created - Put(context.Context, []byte) (string, error) + Put(ctx context.Context, value []byte) (string, error) // Access - Access the latest version of this secret - Access(context.Context) (SecretValue, error) + Access(ctx context.Context) (SecretValue, error) // AccessVersion - Access a specific version of the secret - AccessVersion(context.Context, string) (SecretValue, error) + AccessVersion(ctx context.Context, version string) (SecretValue, error) } var _ SecretClientIface = (*SecretClient)(nil) @@ -54,12 +54,12 @@ func (s *SecretClient) Name() string { } // Put - Store a new value in this secret, returning a reference to the new version created -func (s *SecretClient) Put(ctx context.Context, sec []byte) (string, error) { +func (s *SecretClient) Put(ctx context.Context, value []byte) (string, error) { resp, err := s.secretClient.Put(ctx, &v1.SecretPutRequest{ Secret: &v1.Secret{ Name: s.name, }, - Value: sec, + Value: value, }) if err != nil { return "", errors.FromGrpcError(err) diff --git a/nitric/secrets/secret.go b/nitric/secrets/secret.go index ece6d15..6c3972e 100644 --- a/nitric/secrets/secret.go +++ b/nitric/secrets/secret.go @@ -32,7 +32,7 @@ var SecretEverything []SecretPermission = []SecretPermission{SecretAccess, Secre type Secret interface { // Allow requests the given permissions to the secret. - Allow(SecretPermission, ...SecretPermission) *SecretClient + Allow(permission SecretPermission, permissions ...SecretPermission) *SecretClient } type secret struct { diff --git a/nitric/sql/client.go b/nitric/sql/client.go index d50e781..4670576 100644 --- a/nitric/sql/client.go +++ b/nitric/sql/client.go @@ -28,7 +28,7 @@ type SqlClientIface interface { // Name - The name of the store Name() string // Get a value from the store - ConnectionString(context.Context) (string, error) + ConnectionString(ctx context.Context) (string, error) } type SqlClient struct { diff --git a/nitric/storage/bucket.go b/nitric/storage/bucket.go index 04304fe..e0b04d9 100644 --- a/nitric/storage/bucket.go +++ b/nitric/storage/bucket.go @@ -34,7 +34,7 @@ type bucket struct { type Bucket interface { // Allow requests the given permissions to the bucket. - Allow(BucketPermission, ...BucketPermission) *BucketClient + Allow(permission BucketPermission, permissions ...BucketPermission) *BucketClient // On registers a handler for a specific event type on the bucket. // Valid function signatures for handler are: diff --git a/nitric/topics/client.go b/nitric/topics/client.go index 09c63a2..629df92 100644 --- a/nitric/topics/client.go +++ b/nitric/topics/client.go @@ -35,7 +35,7 @@ type TopicClientIface interface { Name() string // Publish will publish the provided events on the topic. - Publish(context.Context, map[string]interface{}, ...PublishOption) error + Publish(ctx context.Context, message map[string]interface{}, options ...PublishOption) error } type TopicClient struct { diff --git a/nitric/topics/topic.go b/nitric/topics/topic.go index 5cd4314..1df2937 100644 --- a/nitric/topics/topic.go +++ b/nitric/topics/topic.go @@ -33,7 +33,7 @@ const ( type SubscribableTopic interface { // Allow requests the given permissions to the topic. - Allow(TopicPermission, ...TopicPermission) *TopicClient + Allow(permission TopicPermission, permissions ...TopicPermission) *TopicClient // Subscribe will register and start a subscription handler that will be called for all events from this topic. // Valid function signatures for handler are: @@ -43,7 +43,7 @@ type SubscribableTopic interface { // func(*topics.Ctx) // func(*topics.Ctx) error // Handler[topics.Ctx] - Subscribe(interface{}) + Subscribe(handler interface{}) } type subscribableTopic struct {