rbd: add aws-sts-metdata encryption type

With Amazon STS and kubernetes cluster is configured with
OIDC identity provider, credentials to access Amazon KMS
can be fetched using oidc-token(serviceaccount token).
Each tenant/namespace needs to create a secret with aws region,
role and CMK ARN.
Ceph-CSI will assume the given role with oidc token and access
aws KMS, with given CMK to encrypt/decrypt DEK which will stored
in the image metdata.

Refer: https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html
Resolves: #2879

Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
Rakshith R
2022-03-02 16:00:48 +05:30
committed by mergify[bot]
parent 13dcc89ac8
commit 4f0bb2315b
217 changed files with 24757 additions and 72 deletions

67
vendor/github.com/aws/smithy-go/middleware/doc.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
// Package middleware provides transport agnostic middleware for decorating SDK
// handlers.
//
// The Smithy middleware stack provides ordered behavior to be invoked on an
// underlying handler. The stack is separated into steps that are invoked in a
// static order. A step is a collection of middleware that are injected into a
// ordered list defined by the user. The user may add, insert, swap, and remove a
// step's middleware. When the stack is invoked the step middleware become static,
// and their order cannot be modified.
//
// A stack and its step middleware are **not** safe to modify concurrently.
//
// A stack will use the ordered list of middleware to decorate a underlying
// handler. A handler could be something like an HTTP Client that round trips an
// API operation over HTTP.
//
// Smithy Middleware Stack
//
// A Stack is a collection of middleware that wrap a handler. The stack can be
// broken down into discreet steps. Each step may contain zero or more middleware
// specific to that stack's step.
//
// A Stack Step is a predefined set of middleware that are invoked in a static
// order by the Stack. These steps represent fixed points in the middleware stack
// for organizing specific behavior, such as serialize and build. A Stack Step is
// composed of zero or more middleware that are specific to that step. A step may
// define its own set of input/output parameters the generic input/output
// parameters are cast from. A step calls its middleware recursively, before
// calling the next step in the stack returning the result or error of the step
// middleware decorating the underlying handler.
//
// * Initialize: Prepares the input, and sets any default parameters as needed,
// (e.g. idempotency token, and presigned URLs).
//
// * Serialize: Serializes the prepared input into a data structure that can be
// consumed by the target transport's message, (e.g. REST-JSON serialization).
//
// * Build: Adds additional metadata to the serialized transport message, (e.g.
// HTTP's Content-Length header, or body checksum). Decorations and
// modifications to the message should be copied to all message attempts.
//
// * Finalize: Performs final preparations needed before sending the message. The
// message should already be complete by this stage, and is only alternated to
// meet the expectations of the recipient, (e.g. Retry and AWS SigV4 request
// signing).
//
// * Deserialize: Reacts to the handler's response returned by the recipient of
// the request message. Deserializes the response into a structured type or
// error above stacks can react to.
//
// Adding Middleware to a Stack Step
//
// Middleware can be added to a step front or back, or relative, by name, to an
// existing middleware in that stack. If a middleware does not have a name, a
// unique name will be generated at the middleware and be added to the step.
//
// // Create middleware stack
// stack := middleware.NewStack()
//
// // Add middleware to stack steps
// stack.Initialize.Add(paramValidationMiddleware, middleware.After)
// stack.Serialize.Add(marshalOperationFoo, middleware.After)
// stack.Deserialize.Add(unmarshalOperationFoo, middleware.After)
//
// // Invoke middleware on handler.
// resp, err := stack.HandleMiddleware(ctx, req.Input, clientHandler)
package middleware

46
vendor/github.com/aws/smithy-go/middleware/logging.go generated vendored Normal file
View File

@ -0,0 +1,46 @@
package middleware
import (
"context"
"github.com/aws/smithy-go/logging"
)
// loggerKey is the context value key for which the logger is associated with.
type loggerKey struct{}
// GetLogger takes a context to retrieve a Logger from. If no logger is present on the context a logging.Nop logger
// is returned. If the logger retrieved from context supports the ContextLogger interface, the context will be passed
// to the WithContext method and the resulting logger will be returned. Otherwise the stored logger is returned as is.
func GetLogger(ctx context.Context) logging.Logger {
logger, ok := ctx.Value(loggerKey{}).(logging.Logger)
if !ok || logger == nil {
return logging.Nop{}
}
return logging.WithContext(ctx, logger)
}
// SetLogger sets the provided logger value on the provided ctx.
func SetLogger(ctx context.Context, logger logging.Logger) context.Context {
return context.WithValue(ctx, loggerKey{}, logger)
}
type setLogger struct {
Logger logging.Logger
}
// AddSetLoggerMiddleware adds a middleware that will add the provided logger to the middleware context.
func AddSetLoggerMiddleware(stack *Stack, logger logging.Logger) error {
return stack.Initialize.Add(&setLogger{Logger: logger}, After)
}
func (a *setLogger) ID() string {
return "SetLogger"
}
func (a *setLogger) HandleInitialize(ctx context.Context, in InitializeInput, next InitializeHandler) (
out InitializeOutput, metadata Metadata, err error,
) {
return next.HandleInitialize(SetLogger(ctx, a.Logger), in)
}

65
vendor/github.com/aws/smithy-go/middleware/metadata.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
package middleware
// MetadataReader provides an interface for reading metadata from the
// underlying metadata container.
type MetadataReader interface {
Get(key interface{}) interface{}
}
// Metadata provides storing and reading metadata values. Keys may be any
// comparable value type. Get and set will panic if key is not a comparable
// value type.
//
// Metadata uses lazy initialization, and Set method must be called as an
// addressable value, or pointer. Not doing so may cause key/value pair to not
// be set.
type Metadata struct {
values map[interface{}]interface{}
}
// Get attempts to retrieve the value the key points to. Returns nil if the
// key was not found.
//
// Panics if key type is not comparable.
func (m Metadata) Get(key interface{}) interface{} {
return m.values[key]
}
// Clone creates a shallow copy of Metadata entries, returning a new Metadata
// value with the original entries copied into it.
func (m Metadata) Clone() Metadata {
vs := make(map[interface{}]interface{}, len(m.values))
for k, v := range m.values {
vs[k] = v
}
return Metadata{
values: vs,
}
}
// Set stores the value pointed to by the key. If a value already exists at
// that key it will be replaced with the new value.
//
// Set method must be called as an addressable value, or pointer. If Set is not
// called as an addressable value or pointer, the key value pair being set may
// be lost.
//
// Panics if the key type is not comparable.
func (m *Metadata) Set(key, value interface{}) {
if m.values == nil {
m.values = map[interface{}]interface{}{}
}
m.values[key] = value
}
// Has returns whether the key exists in the metadata.
//
// Panics if the key type is not comparable.
func (m Metadata) Has(key interface{}) bool {
if m.values == nil {
return false
}
_, ok := m.values[key]
return ok
}

View File

@ -0,0 +1,71 @@
package middleware
import (
"context"
)
// Handler provides the interface for performing the logic to obtain an output,
// or error for the given input.
type Handler interface {
// Handle performs logic to obtain an output for the given input. Handler
// should be decorated with middleware to perform input specific behavior.
Handle(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
)
}
// HandlerFunc provides a wrapper around a function pointer to be used as a
// middleware handler.
type HandlerFunc func(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
)
// Handle invokes the underlying function, returning the result.
func (fn HandlerFunc) Handle(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
) {
return fn(ctx, input)
}
// Middleware provides the interface to call handlers in a chain.
type Middleware interface {
// ID provides a unique identifier for the middleware.
ID() string
// Performs the middleware's handling of the input, returning the output,
// or error. The middleware can invoke the next Handler if handling should
// continue.
HandleMiddleware(ctx context.Context, input interface{}, next Handler) (
output interface{}, metadata Metadata, err error,
)
}
// decoratedHandler wraps a middleware in order to to call the next handler in
// the chain.
type decoratedHandler struct {
// The next handler to be called.
Next Handler
// The current middleware decorating the handler.
With Middleware
}
// Handle implements the Handler interface to handle a operation invocation.
func (m decoratedHandler) Handle(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
) {
return m.With.HandleMiddleware(ctx, input, m.Next)
}
// DecorateHandler decorates a handler with a middleware. Wrapping the handler
// with the middleware.
func DecorateHandler(h Handler, with ...Middleware) Handler {
for i := len(with) - 1; i >= 0; i-- {
h = decoratedHandler{
Next: h,
With: with[i],
}
}
return h
}

View File

@ -0,0 +1,268 @@
package middleware
import "fmt"
// RelativePosition provides specifying the relative position of a middleware
// in an ordered group.
type RelativePosition int
// Relative position for middleware in steps.
const (
After RelativePosition = iota
Before
)
type ider interface {
ID() string
}
// orderedIDs provides an ordered collection of items with relative ordering
// by name.
type orderedIDs struct {
order *relativeOrder
items map[string]ider
}
const baseOrderedItems = 5
func newOrderedIDs() *orderedIDs {
return &orderedIDs{
order: newRelativeOrder(),
items: make(map[string]ider, baseOrderedItems),
}
}
// Add injects the item to the relative position of the item group. Returns an
// error if the item already exists.
func (g *orderedIDs) Add(m ider, pos RelativePosition) error {
id := m.ID()
if len(id) == 0 {
return fmt.Errorf("empty ID, ID must not be empty")
}
if err := g.order.Add(pos, id); err != nil {
return err
}
g.items[id] = m
return nil
}
// Insert injects the item relative to an existing item id. Returns an error if
// the original item does not exist, or the item being added already exists.
func (g *orderedIDs) Insert(m ider, relativeTo string, pos RelativePosition) error {
if len(m.ID()) == 0 {
return fmt.Errorf("insert ID must not be empty")
}
if len(relativeTo) == 0 {
return fmt.Errorf("relative to ID must not be empty")
}
if err := g.order.Insert(relativeTo, pos, m.ID()); err != nil {
return err
}
g.items[m.ID()] = m
return nil
}
// Get returns the ider identified by id. If ider is not present, returns false.
func (g *orderedIDs) Get(id string) (ider, bool) {
v, ok := g.items[id]
return v, ok
}
// Swap removes the item by id, replacing it with the new item. Returns an error
// if the original item doesn't exist.
func (g *orderedIDs) Swap(id string, m ider) (ider, error) {
if len(id) == 0 {
return nil, fmt.Errorf("swap from ID must not be empty")
}
iderID := m.ID()
if len(iderID) == 0 {
return nil, fmt.Errorf("swap to ID must not be empty")
}
if err := g.order.Swap(id, iderID); err != nil {
return nil, err
}
removed := g.items[id]
delete(g.items, id)
g.items[iderID] = m
return removed, nil
}
// Remove removes the item by id. Returns an error if the item
// doesn't exist.
func (g *orderedIDs) Remove(id string) (ider, error) {
if len(id) == 0 {
return nil, fmt.Errorf("remove ID must not be empty")
}
if err := g.order.Remove(id); err != nil {
return nil, err
}
removed := g.items[id]
delete(g.items, id)
return removed, nil
}
func (g *orderedIDs) List() []string {
items := g.order.List()
order := make([]string, len(items))
copy(order, items)
return order
}
// Clear removes all entries and slots.
func (g *orderedIDs) Clear() {
g.order.Clear()
g.items = map[string]ider{}
}
// GetOrder returns the item in the order it should be invoked in.
func (g *orderedIDs) GetOrder() []interface{} {
order := g.order.List()
ordered := make([]interface{}, len(order))
for i := 0; i < len(order); i++ {
ordered[i] = g.items[order[i]]
}
return ordered
}
// relativeOrder provides ordering of item
type relativeOrder struct {
order []string
}
func newRelativeOrder() *relativeOrder {
return &relativeOrder{
order: make([]string, 0, baseOrderedItems),
}
}
// Add inserts an item into the order relative to the position provided.
func (s *relativeOrder) Add(pos RelativePosition, ids ...string) error {
if len(ids) == 0 {
return nil
}
for _, id := range ids {
if _, ok := s.has(id); ok {
return fmt.Errorf("already exists, %v", id)
}
}
switch pos {
case Before:
return s.insert(0, Before, ids...)
case After:
s.order = append(s.order, ids...)
default:
return fmt.Errorf("invalid position, %v", int(pos))
}
return nil
}
// Insert injects an item before or after the relative item. Returns
// an error if the relative item does not exist.
func (s *relativeOrder) Insert(relativeTo string, pos RelativePosition, ids ...string) error {
if len(ids) == 0 {
return nil
}
for _, id := range ids {
if _, ok := s.has(id); ok {
return fmt.Errorf("already exists, %v", id)
}
}
i, ok := s.has(relativeTo)
if !ok {
return fmt.Errorf("not found, %v", relativeTo)
}
return s.insert(i, pos, ids...)
}
// Swap will replace the item id with the to item. Returns an
// error if the original item id does not exist. Allows swapping out an
// item for another item with the same id.
func (s *relativeOrder) Swap(id, to string) error {
i, ok := s.has(id)
if !ok {
return fmt.Errorf("not found, %v", id)
}
if _, ok = s.has(to); ok && id != to {
return fmt.Errorf("already exists, %v", to)
}
s.order[i] = to
return nil
}
func (s *relativeOrder) Remove(id string) error {
i, ok := s.has(id)
if !ok {
return fmt.Errorf("not found, %v", id)
}
s.order = append(s.order[:i], s.order[i+1:]...)
return nil
}
func (s *relativeOrder) List() []string {
return s.order
}
func (s *relativeOrder) Clear() {
s.order = s.order[0:0]
}
func (s *relativeOrder) insert(i int, pos RelativePosition, ids ...string) error {
switch pos {
case Before:
n := len(ids)
var src []string
if n <= cap(s.order)-len(s.order) {
s.order = s.order[:len(s.order)+n]
src = s.order
} else {
src = s.order
s.order = make([]string, len(s.order)+n)
copy(s.order[:i], src[:i]) // only when allocating a new slice do we need to copy the front half
}
copy(s.order[i+n:], src[i:])
copy(s.order[i:], ids)
case After:
if i == len(s.order)-1 || len(s.order) == 0 {
s.order = append(s.order, ids...)
} else {
s.order = append(s.order[:i+1], append(ids, s.order[i+1:]...)...)
}
default:
return fmt.Errorf("invalid position, %v", int(pos))
}
return nil
}
func (s *relativeOrder) has(id string) (i int, found bool) {
for i := 0; i < len(s.order); i++ {
if s.order[i] == id {
return i, true
}
}
return 0, false
}

209
vendor/github.com/aws/smithy-go/middleware/stack.go generated vendored Normal file
View File

@ -0,0 +1,209 @@
package middleware
import (
"context"
"io"
"strings"
)
// Stack provides protocol and transport agnostic set of middleware split into
// distinct steps. Steps have specific transitions between them, that are
// managed by the individual step.
//
// Steps are composed as middleware around the underlying handler in the
// following order:
//
// Initialize -> Serialize -> Build -> Finalize -> Deserialize -> Handler
//
// Any middleware within the chain may choose to stop and return an error or
// response. Since the middleware decorate the handler like a call stack, each
// middleware will receive the result of the next middleware in the chain.
// Middleware that does not need to react to an input, or result must forward
// along the input down the chain, or return the result back up the chain.
//
// Initialize <- Serialize -> Build -> Finalize <- Deserialize <- Handler
type Stack struct {
// Initialize prepares the input, and sets any default parameters as
// needed, (e.g. idempotency token, and presigned URLs).
//
// Takes Input Parameters, and returns result or error.
//
// Receives result or error from Serialize step.
Initialize *InitializeStep
// Serialize serializes the prepared input into a data structure that can be consumed
// by the target transport's message, (e.g. REST-JSON serialization)
//
// Converts Input Parameters into a Request, and returns the result or error.
//
// Receives result or error from Build step.
Serialize *SerializeStep
// Build adds additional metadata to the serialized transport message
// (e.g. HTTP's Content-Length header, or body checksum). Decorations and
// modifications to the message should be copied to all message attempts.
//
// Takes Request, and returns result or error.
//
// Receives result or error from Finalize step.
Build *BuildStep
// Finalize performs final preparations needed before sending the message. The
// message should already be complete by this stage, and is only alternated
// to meet the expectations of the recipient (e.g. Retry and AWS SigV4
// request signing)
//
// Takes Request, and returns result or error.
//
// Receives result or error from Deserialize step.
Finalize *FinalizeStep
// Deserialize reacts to the handler's response returned by the recipient of the request
// message. Deserializes the response into a structured type or error above
// stacks can react to.
//
// Should only forward Request to underlying handler.
//
// Takes Request, and returns result or error.
//
// Receives raw response, or error from underlying handler.
Deserialize *DeserializeStep
id string
}
// NewStack returns an initialize empty stack.
func NewStack(id string, newRequestFn func() interface{}) *Stack {
return &Stack{
id: id,
Initialize: NewInitializeStep(),
Serialize: NewSerializeStep(newRequestFn),
Build: NewBuildStep(),
Finalize: NewFinalizeStep(),
Deserialize: NewDeserializeStep(),
}
}
// ID returns the unique ID for the stack as a middleware.
func (s *Stack) ID() string { return s.id }
// HandleMiddleware invokes the middleware stack decorating the next handler.
// Each step of stack will be invoked in order before calling the next step.
// With the next handler call last.
//
// The input value must be the input parameters of the operation being
// performed.
//
// Will return the result of the operation, or error.
func (s *Stack) HandleMiddleware(ctx context.Context, input interface{}, next Handler) (
output interface{}, metadata Metadata, err error,
) {
h := DecorateHandler(next,
s.Initialize,
s.Serialize,
s.Build,
s.Finalize,
s.Deserialize,
)
return h.Handle(ctx, input)
}
// List returns a list of all middleware in the stack by step.
func (s *Stack) List() []string {
var l []string
l = append(l, s.id)
l = append(l, s.Initialize.ID())
l = append(l, s.Initialize.List()...)
l = append(l, s.Serialize.ID())
l = append(l, s.Serialize.List()...)
l = append(l, s.Build.ID())
l = append(l, s.Build.List()...)
l = append(l, s.Finalize.ID())
l = append(l, s.Finalize.List()...)
l = append(l, s.Deserialize.ID())
l = append(l, s.Deserialize.List()...)
return l
}
func (s *Stack) String() string {
var b strings.Builder
w := &indentWriter{w: &b}
w.WriteLine(s.id)
w.Push()
writeStepItems(w, s.Initialize)
writeStepItems(w, s.Serialize)
writeStepItems(w, s.Build)
writeStepItems(w, s.Finalize)
writeStepItems(w, s.Deserialize)
return b.String()
}
type stackStepper interface {
ID() string
List() []string
}
func writeStepItems(w *indentWriter, s stackStepper) {
type lister interface {
List() []string
}
w.WriteLine(s.ID())
w.Push()
defer w.Pop()
// ignore stack to prevent circular iterations
if _, ok := s.(*Stack); ok {
return
}
for _, id := range s.List() {
w.WriteLine(id)
}
}
type stringWriter interface {
io.Writer
WriteString(string) (int, error)
WriteRune(rune) (int, error)
}
type indentWriter struct {
w stringWriter
depth int
}
const indentDepth = "\t\t\t\t\t\t\t\t\t\t"
func (w *indentWriter) Push() {
w.depth++
}
func (w *indentWriter) Pop() {
w.depth--
if w.depth < 0 {
w.depth = 0
}
}
func (w *indentWriter) WriteLine(v string) {
w.w.WriteString(indentDepth[:w.depth])
v = strings.ReplaceAll(v, "\n", "\\n")
v = strings.ReplaceAll(v, "\r", "\\r")
w.w.WriteString(v)
w.w.WriteRune('\n')
}

View File

@ -0,0 +1,100 @@
package middleware
import (
"context"
"reflect"
"strings"
)
// WithStackValue adds a key value pair to the context that is intended to be
// scoped to a stack. Use ClearStackValues to get a new context with all stack
// values cleared.
func WithStackValue(ctx context.Context, key, value interface{}) context.Context {
md, _ := ctx.Value(stackValuesKey{}).(*stackValues)
md = withStackValue(md, key, value)
return context.WithValue(ctx, stackValuesKey{}, md)
}
// ClearStackValues returns a context without any stack values.
func ClearStackValues(ctx context.Context) context.Context {
return context.WithValue(ctx, stackValuesKey{}, nil)
}
// GetStackValues returns the value pointed to by the key within the stack
// values, if it is present.
func GetStackValue(ctx context.Context, key interface{}) interface{} {
md, _ := ctx.Value(stackValuesKey{}).(*stackValues)
if md == nil {
return nil
}
return md.Value(key)
}
type stackValuesKey struct{}
type stackValues struct {
key interface{}
value interface{}
parent *stackValues
}
func withStackValue(parent *stackValues, key, value interface{}) *stackValues {
if key == nil {
panic("nil key")
}
if !reflect.TypeOf(key).Comparable() {
panic("key is not comparable")
}
return &stackValues{key: key, value: value, parent: parent}
}
func (m *stackValues) Value(key interface{}) interface{} {
if key == m.key {
return m.value
}
if m.parent == nil {
return nil
}
return m.parent.Value(key)
}
func (c *stackValues) String() string {
var str strings.Builder
cc := c
for cc == nil {
str.WriteString("(" +
reflect.TypeOf(c.key).String() +
": " +
stringify(cc.value) +
")")
if cc.parent != nil {
str.WriteString(" -> ")
}
cc = cc.parent
}
str.WriteRune('}')
return str.String()
}
type stringer interface {
String() string
}
// stringify tries a bit to stringify v, without using fmt, since we don't
// want context depending on the unicode tables. This is only used by
// *valueCtx.String().
func stringify(v interface{}) string {
switch s := v.(type) {
case stringer:
return s.String()
case string:
return s
}
return "<not Stringer>"
}

View File

@ -0,0 +1,211 @@
package middleware
import (
"context"
)
// BuildInput provides the input parameters for the BuildMiddleware to consume.
// BuildMiddleware may modify the Request value before forwarding the input
// along to the next BuildHandler.
type BuildInput struct {
Request interface{}
}
// BuildOutput provides the result returned by the next BuildHandler.
type BuildOutput struct {
Result interface{}
}
// BuildHandler provides the interface for the next handler the
// BuildMiddleware will call in the middleware chain.
type BuildHandler interface {
HandleBuild(ctx context.Context, in BuildInput) (
out BuildOutput, metadata Metadata, err error,
)
}
// BuildMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next BuildHandler for further
// processing.
type BuildMiddleware interface {
// Unique ID for the middleware in theBuildStep. The step does not allow
// duplicate IDs.
ID() string
// Invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleBuild(ctx context.Context, in BuildInput, next BuildHandler) (
out BuildOutput, metadata Metadata, err error,
)
}
// BuildMiddlewareFunc returns a BuildMiddleware with the unique ID provided,
// and the func to be invoked.
func BuildMiddlewareFunc(id string, fn func(context.Context, BuildInput, BuildHandler) (BuildOutput, Metadata, error)) BuildMiddleware {
return buildMiddlewareFunc{
id: id,
fn: fn,
}
}
type buildMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, BuildInput, BuildHandler) (BuildOutput, Metadata, error)
}
// ID returns the unique ID for the middleware.
func (s buildMiddlewareFunc) ID() string { return s.id }
// HandleBuild invokes the middleware Fn.
func (s buildMiddlewareFunc) HandleBuild(ctx context.Context, in BuildInput, next BuildHandler) (
out BuildOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ BuildMiddleware = (buildMiddlewareFunc{})
// BuildStep provides the ordered grouping of BuildMiddleware to be invoked on
// a handler.
type BuildStep struct {
ids *orderedIDs
}
// NewBuildStep returns a BuildStep ready to have middleware for
// initialization added to it.
func NewBuildStep() *BuildStep {
return &BuildStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*BuildStep)(nil)
// ID returns the unique name of the step as a middleware.
func (s *BuildStep) ID() string {
return "Build stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *BuildStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h BuildHandler = buildWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedBuildHandler{
Next: h,
With: order[i].(BuildMiddleware),
}
}
sIn := BuildInput{
Request: in,
}
res, metadata, err := h.HandleBuild(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *BuildStep) Get(id string) (BuildMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(BuildMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *BuildStep) Add(m BuildMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware id.
// Returns an error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *BuildStep) Insert(m BuildMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or an error if the middleware to be removed
// doesn't exist.
func (s *BuildStep) Swap(id string, m BuildMiddleware) (BuildMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(BuildMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *BuildStep) Remove(id string) (BuildMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(BuildMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *BuildStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *BuildStep) Clear() {
s.ids.Clear()
}
type buildWrapHandler struct {
Next Handler
}
var _ BuildHandler = (*buildWrapHandler)(nil)
// Implements BuildHandler, converts types and delegates to underlying
// generic handler.
func (w buildWrapHandler) HandleBuild(ctx context.Context, in BuildInput) (
out BuildOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Request)
return BuildOutput{
Result: res,
}, metadata, err
}
type decoratedBuildHandler struct {
Next BuildHandler
With BuildMiddleware
}
var _ BuildHandler = (*decoratedBuildHandler)(nil)
func (h decoratedBuildHandler) HandleBuild(ctx context.Context, in BuildInput) (
out BuildOutput, metadata Metadata, err error,
) {
return h.With.HandleBuild(ctx, in, h.Next)
}
// BuildHandlerFunc provides a wrapper around a function to be used as a build middleware handler.
type BuildHandlerFunc func(context.Context, BuildInput) (BuildOutput, Metadata, error)
// HandleBuild invokes the wrapped function with the provided arguments.
func (b BuildHandlerFunc) HandleBuild(ctx context.Context, in BuildInput) (BuildOutput, Metadata, error) {
return b(ctx, in)
}
var _ BuildHandler = BuildHandlerFunc(nil)

View File

@ -0,0 +1,217 @@
package middleware
import (
"context"
)
// DeserializeInput provides the input parameters for the DeserializeInput to
// consume. DeserializeMiddleware should not modify the Request, and instead
// forward it along to the next DeserializeHandler.
type DeserializeInput struct {
Request interface{}
}
// DeserializeOutput provides the result returned by the next
// DeserializeHandler. The DeserializeMiddleware should deserialize the
// RawResponse into a Result that can be consumed by middleware higher up in
// the stack.
type DeserializeOutput struct {
RawResponse interface{}
Result interface{}
}
// DeserializeHandler provides the interface for the next handler the
// DeserializeMiddleware will call in the middleware chain.
type DeserializeHandler interface {
HandleDeserialize(ctx context.Context, in DeserializeInput) (
out DeserializeOutput, metadata Metadata, err error,
)
}
// DeserializeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next DeserializeHandler for further
// processing.
type DeserializeMiddleware interface {
// ID returns a unique ID for the middleware in the DeserializeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleDeserialize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleDeserialize(ctx context.Context, in DeserializeInput, next DeserializeHandler) (
out DeserializeOutput, metadata Metadata, err error,
)
}
// DeserializeMiddlewareFunc returns a DeserializeMiddleware with the unique ID
// provided, and the func to be invoked.
func DeserializeMiddlewareFunc(id string, fn func(context.Context, DeserializeInput, DeserializeHandler) (DeserializeOutput, Metadata, error)) DeserializeMiddleware {
return deserializeMiddlewareFunc{
id: id,
fn: fn,
}
}
type deserializeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, DeserializeInput, DeserializeHandler) (
DeserializeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s deserializeMiddlewareFunc) ID() string { return s.id }
// HandleDeserialize invokes the middleware Fn.
func (s deserializeMiddlewareFunc) HandleDeserialize(ctx context.Context, in DeserializeInput, next DeserializeHandler) (
out DeserializeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ DeserializeMiddleware = (deserializeMiddlewareFunc{})
// DeserializeStep provides the ordered grouping of DeserializeMiddleware to be
// invoked on a handler.
type DeserializeStep struct {
ids *orderedIDs
}
// NewDeserializeStep returns a DeserializeStep ready to have middleware for
// initialization added to it.
func NewDeserializeStep() *DeserializeStep {
return &DeserializeStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*DeserializeStep)(nil)
// ID returns the unique ID of the step as a middleware.
func (s *DeserializeStep) ID() string {
return "Deserialize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *DeserializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h DeserializeHandler = deserializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedDeserializeHandler{
Next: h,
With: order[i].(DeserializeMiddleware),
}
}
sIn := DeserializeInput{
Request: in,
}
res, metadata, err := h.HandleDeserialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *DeserializeStep) Get(id string) (DeserializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(DeserializeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *DeserializeStep) Add(m DeserializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *DeserializeStep) Insert(m DeserializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *DeserializeStep) Swap(id string, m DeserializeMiddleware) (DeserializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(DeserializeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *DeserializeStep) Remove(id string) (DeserializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(DeserializeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *DeserializeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *DeserializeStep) Clear() {
s.ids.Clear()
}
type deserializeWrapHandler struct {
Next Handler
}
var _ DeserializeHandler = (*deserializeWrapHandler)(nil)
// HandleDeserialize implements DeserializeHandler, converts types and delegates to underlying
// generic handler.
func (w deserializeWrapHandler) HandleDeserialize(ctx context.Context, in DeserializeInput) (
out DeserializeOutput, metadata Metadata, err error,
) {
resp, metadata, err := w.Next.Handle(ctx, in.Request)
return DeserializeOutput{
RawResponse: resp,
}, metadata, err
}
type decoratedDeserializeHandler struct {
Next DeserializeHandler
With DeserializeMiddleware
}
var _ DeserializeHandler = (*decoratedDeserializeHandler)(nil)
func (h decoratedDeserializeHandler) HandleDeserialize(ctx context.Context, in DeserializeInput) (
out DeserializeOutput, metadata Metadata, err error,
) {
return h.With.HandleDeserialize(ctx, in, h.Next)
}
// DeserializeHandlerFunc provides a wrapper around a function to be used as a deserialize middleware handler.
type DeserializeHandlerFunc func(context.Context, DeserializeInput) (DeserializeOutput, Metadata, error)
// HandleDeserialize invokes the wrapped function with the given arguments.
func (d DeserializeHandlerFunc) HandleDeserialize(ctx context.Context, in DeserializeInput) (DeserializeOutput, Metadata, error) {
return d(ctx, in)
}
var _ DeserializeHandler = DeserializeHandlerFunc(nil)

View File

@ -0,0 +1,211 @@
package middleware
import "context"
// FinalizeInput provides the input parameters for the FinalizeMiddleware to
// consume. FinalizeMiddleware may modify the Request value before forwarding
// the FinalizeInput along to the next next FinalizeHandler.
type FinalizeInput struct {
Request interface{}
}
// FinalizeOutput provides the result returned by the next FinalizeHandler.
type FinalizeOutput struct {
Result interface{}
}
// FinalizeHandler provides the interface for the next handler the
// FinalizeMiddleware will call in the middleware chain.
type FinalizeHandler interface {
HandleFinalize(ctx context.Context, in FinalizeInput) (
out FinalizeOutput, metadata Metadata, err error,
)
}
// FinalizeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next FinalizeHandler for further
// processing.
type FinalizeMiddleware interface {
// ID returns a unique ID for the middleware in the FinalizeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleFinalize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleFinalize(ctx context.Context, in FinalizeInput, next FinalizeHandler) (
out FinalizeOutput, metadata Metadata, err error,
)
}
// FinalizeMiddlewareFunc returns a FinalizeMiddleware with the unique ID
// provided, and the func to be invoked.
func FinalizeMiddlewareFunc(id string, fn func(context.Context, FinalizeInput, FinalizeHandler) (FinalizeOutput, Metadata, error)) FinalizeMiddleware {
return finalizeMiddlewareFunc{
id: id,
fn: fn,
}
}
type finalizeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, FinalizeInput, FinalizeHandler) (
FinalizeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s finalizeMiddlewareFunc) ID() string { return s.id }
// HandleFinalize invokes the middleware Fn.
func (s finalizeMiddlewareFunc) HandleFinalize(ctx context.Context, in FinalizeInput, next FinalizeHandler) (
out FinalizeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ FinalizeMiddleware = (finalizeMiddlewareFunc{})
// FinalizeStep provides the ordered grouping of FinalizeMiddleware to be
// invoked on a handler.
type FinalizeStep struct {
ids *orderedIDs
}
// NewFinalizeStep returns a FinalizeStep ready to have middleware for
// initialization added to it.
func NewFinalizeStep() *FinalizeStep {
return &FinalizeStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*FinalizeStep)(nil)
// ID returns the unique id of the step as a middleware.
func (s *FinalizeStep) ID() string {
return "Finalize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *FinalizeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h FinalizeHandler = finalizeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedFinalizeHandler{
Next: h,
With: order[i].(FinalizeMiddleware),
}
}
sIn := FinalizeInput{
Request: in,
}
res, metadata, err := h.HandleFinalize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *FinalizeStep) Get(id string) (FinalizeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(FinalizeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *FinalizeStep) Add(m FinalizeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *FinalizeStep) Insert(m FinalizeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *FinalizeStep) Swap(id string, m FinalizeMiddleware) (FinalizeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(FinalizeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *FinalizeStep) Remove(id string) (FinalizeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(FinalizeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *FinalizeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *FinalizeStep) Clear() {
s.ids.Clear()
}
type finalizeWrapHandler struct {
Next Handler
}
var _ FinalizeHandler = (*finalizeWrapHandler)(nil)
// HandleFinalize implements FinalizeHandler, converts types and delegates to underlying
// generic handler.
func (w finalizeWrapHandler) HandleFinalize(ctx context.Context, in FinalizeInput) (
out FinalizeOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Request)
return FinalizeOutput{
Result: res,
}, metadata, err
}
type decoratedFinalizeHandler struct {
Next FinalizeHandler
With FinalizeMiddleware
}
var _ FinalizeHandler = (*decoratedFinalizeHandler)(nil)
func (h decoratedFinalizeHandler) HandleFinalize(ctx context.Context, in FinalizeInput) (
out FinalizeOutput, metadata Metadata, err error,
) {
return h.With.HandleFinalize(ctx, in, h.Next)
}
// FinalizeHandlerFunc provides a wrapper around a function to be used as a finalize middleware handler.
type FinalizeHandlerFunc func(context.Context, FinalizeInput) (FinalizeOutput, Metadata, error)
// HandleFinalize invokes the wrapped function with the given arguments.
func (f FinalizeHandlerFunc) HandleFinalize(ctx context.Context, in FinalizeInput) (FinalizeOutput, Metadata, error) {
return f(ctx, in)
}
var _ FinalizeHandler = FinalizeHandlerFunc(nil)

View File

@ -0,0 +1,211 @@
package middleware
import "context"
// InitializeInput wraps the input parameters for the InitializeMiddlewares to
// consume. InitializeMiddleware may modify the parameter value before
// forwarding it along to the next InitializeHandler.
type InitializeInput struct {
Parameters interface{}
}
// InitializeOutput provides the result returned by the next InitializeHandler.
type InitializeOutput struct {
Result interface{}
}
// InitializeHandler provides the interface for the next handler the
// InitializeMiddleware will call in the middleware chain.
type InitializeHandler interface {
HandleInitialize(ctx context.Context, in InitializeInput) (
out InitializeOutput, metadata Metadata, err error,
)
}
// InitializeMiddleware provides the interface for middleware specific to the
// initialize step. Delegates to the next InitializeHandler for further
// processing.
type InitializeMiddleware interface {
// ID returns a unique ID for the middleware in the InitializeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleInitialize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleInitialize(ctx context.Context, in InitializeInput, next InitializeHandler) (
out InitializeOutput, metadata Metadata, err error,
)
}
// InitializeMiddlewareFunc returns a InitializeMiddleware with the unique ID provided,
// and the func to be invoked.
func InitializeMiddlewareFunc(id string, fn func(context.Context, InitializeInput, InitializeHandler) (InitializeOutput, Metadata, error)) InitializeMiddleware {
return initializeMiddlewareFunc{
id: id,
fn: fn,
}
}
type initializeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, InitializeInput, InitializeHandler) (
InitializeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s initializeMiddlewareFunc) ID() string { return s.id }
// HandleInitialize invokes the middleware Fn.
func (s initializeMiddlewareFunc) HandleInitialize(ctx context.Context, in InitializeInput, next InitializeHandler) (
out InitializeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ InitializeMiddleware = (initializeMiddlewareFunc{})
// InitializeStep provides the ordered grouping of InitializeMiddleware to be
// invoked on a handler.
type InitializeStep struct {
ids *orderedIDs
}
// NewInitializeStep returns an InitializeStep ready to have middleware for
// initialization added to it.
func NewInitializeStep() *InitializeStep {
return &InitializeStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*InitializeStep)(nil)
// ID returns the unique ID of the step as a middleware.
func (s *InitializeStep) ID() string {
return "Initialize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *InitializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h InitializeHandler = initializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedInitializeHandler{
Next: h,
With: order[i].(InitializeMiddleware),
}
}
sIn := InitializeInput{
Parameters: in,
}
res, metadata, err := h.HandleInitialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *InitializeStep) Get(id string) (InitializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(InitializeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *InitializeStep) Add(m InitializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *InitializeStep) Insert(m InitializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *InitializeStep) Swap(id string, m InitializeMiddleware) (InitializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(InitializeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *InitializeStep) Remove(id string) (InitializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(InitializeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *InitializeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *InitializeStep) Clear() {
s.ids.Clear()
}
type initializeWrapHandler struct {
Next Handler
}
var _ InitializeHandler = (*initializeWrapHandler)(nil)
// HandleInitialize implements InitializeHandler, converts types and delegates to underlying
// generic handler.
func (w initializeWrapHandler) HandleInitialize(ctx context.Context, in InitializeInput) (
out InitializeOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Parameters)
return InitializeOutput{
Result: res,
}, metadata, err
}
type decoratedInitializeHandler struct {
Next InitializeHandler
With InitializeMiddleware
}
var _ InitializeHandler = (*decoratedInitializeHandler)(nil)
func (h decoratedInitializeHandler) HandleInitialize(ctx context.Context, in InitializeInput) (
out InitializeOutput, metadata Metadata, err error,
) {
return h.With.HandleInitialize(ctx, in, h.Next)
}
// InitializeHandlerFunc provides a wrapper around a function to be used as an initialize middleware handler.
type InitializeHandlerFunc func(context.Context, InitializeInput) (InitializeOutput, Metadata, error)
// HandleInitialize calls the wrapped function with the provided arguments.
func (i InitializeHandlerFunc) HandleInitialize(ctx context.Context, in InitializeInput) (InitializeOutput, Metadata, error) {
return i(ctx, in)
}
var _ InitializeHandler = InitializeHandlerFunc(nil)

View File

@ -0,0 +1,219 @@
package middleware
import "context"
// SerializeInput provides the input parameters for the SerializeMiddleware to
// consume. SerializeMiddleware may modify the Request value before forwarding
// SerializeInput along to the next SerializeHandler. The Parameters member
// should not be modified by SerializeMiddleware, InitializeMiddleware should
// be responsible for modifying the provided Parameter value.
type SerializeInput struct {
Parameters interface{}
Request interface{}
}
// SerializeOutput provides the result returned by the next SerializeHandler.
type SerializeOutput struct {
Result interface{}
}
// SerializeHandler provides the interface for the next handler the
// SerializeMiddleware will call in the middleware chain.
type SerializeHandler interface {
HandleSerialize(ctx context.Context, in SerializeInput) (
out SerializeOutput, metadata Metadata, err error,
)
}
// SerializeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next SerializeHandler for further
// processing.
type SerializeMiddleware interface {
// ID returns a unique ID for the middleware in the SerializeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleSerialize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleSerialize(ctx context.Context, in SerializeInput, next SerializeHandler) (
out SerializeOutput, metadata Metadata, err error,
)
}
// SerializeMiddlewareFunc returns a SerializeMiddleware with the unique ID
// provided, and the func to be invoked.
func SerializeMiddlewareFunc(id string, fn func(context.Context, SerializeInput, SerializeHandler) (SerializeOutput, Metadata, error)) SerializeMiddleware {
return serializeMiddlewareFunc{
id: id,
fn: fn,
}
}
type serializeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, SerializeInput, SerializeHandler) (
SerializeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s serializeMiddlewareFunc) ID() string { return s.id }
// HandleSerialize invokes the middleware Fn.
func (s serializeMiddlewareFunc) HandleSerialize(ctx context.Context, in SerializeInput, next SerializeHandler) (
out SerializeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ SerializeMiddleware = (serializeMiddlewareFunc{})
// SerializeStep provides the ordered grouping of SerializeMiddleware to be
// invoked on a handler.
type SerializeStep struct {
newRequest func() interface{}
ids *orderedIDs
}
// NewSerializeStep returns a SerializeStep ready to have middleware for
// initialization added to it. The newRequest func parameter is used to
// initialize the transport specific request for the stack SerializeStep to
// serialize the input parameters into.
func NewSerializeStep(newRequest func() interface{}) *SerializeStep {
return &SerializeStep{
ids: newOrderedIDs(),
newRequest: newRequest,
}
}
var _ Middleware = (*SerializeStep)(nil)
// ID returns the unique ID of the step as a middleware.
func (s *SerializeStep) ID() string {
return "Serialize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *SerializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h SerializeHandler = serializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedSerializeHandler{
Next: h,
With: order[i].(SerializeMiddleware),
}
}
sIn := SerializeInput{
Parameters: in,
Request: s.newRequest(),
}
res, metadata, err := h.HandleSerialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *SerializeStep) Get(id string) (SerializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(SerializeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *SerializeStep) Add(m SerializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *SerializeStep) Insert(m SerializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *SerializeStep) Swap(id string, m SerializeMiddleware) (SerializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(SerializeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *SerializeStep) Remove(id string) (SerializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(SerializeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *SerializeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *SerializeStep) Clear() {
s.ids.Clear()
}
type serializeWrapHandler struct {
Next Handler
}
var _ SerializeHandler = (*serializeWrapHandler)(nil)
// Implements SerializeHandler, converts types and delegates to underlying
// generic handler.
func (w serializeWrapHandler) HandleSerialize(ctx context.Context, in SerializeInput) (
out SerializeOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Request)
return SerializeOutput{
Result: res,
}, metadata, err
}
type decoratedSerializeHandler struct {
Next SerializeHandler
With SerializeMiddleware
}
var _ SerializeHandler = (*decoratedSerializeHandler)(nil)
func (h decoratedSerializeHandler) HandleSerialize(ctx context.Context, in SerializeInput) (
out SerializeOutput, metadata Metadata, err error,
) {
return h.With.HandleSerialize(ctx, in, h.Next)
}
// SerializeHandlerFunc provides a wrapper around a function to be used as a serialize middleware handler.
type SerializeHandlerFunc func(context.Context, SerializeInput) (SerializeOutput, Metadata, error)
// HandleSerialize calls the wrapped function with the provided arguments.
func (s SerializeHandlerFunc) HandleSerialize(ctx context.Context, in SerializeInput) (SerializeOutput, Metadata, error) {
return s(ctx, in)
}
var _ SerializeHandler = SerializeHandlerFunc(nil)