From a069e682beb65efc367bbb577b9bb6c5abfb20c6 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Tue, 28 Mar 2023 09:34:20 -0700 Subject: [PATCH] Refactor metadata parsing in middlewares and workflows (#2715) Signed-off-by: Bernd Verst --- metadata/utils.go | 13 ++++--- middleware/http/bearer/bearer_middleware.go | 9 +++++ middleware/http/bearer/metadata.go | 12 +++--- middleware/http/oauth2/oauth2_middleware.go | 24 ++++++++---- .../oauth2clientcredentials_middleware.go | 22 +++++++---- ...oauth2clientcredentials_middleware_test.go | 2 +- middleware/http/opa/middleware.go | 38 ++++++++++--------- .../http/ratelimit/ratelimit_middleware.go | 32 +++++++++------- .../ratelimit/ratelimit_middleware_test.go | 9 +---- .../routeralias/routeralias_middleware.go | 4 ++ .../routerchecker/routerchecker_middleware.go | 10 ++++- middleware/http/sentinel/middleware.go | 22 +++++++---- middleware/http/wasm/httpwasm.go | 23 ++++++----- middleware/middleware.go | 1 + workflows/temporal/temporal.go | 14 +++++-- workflows/workflow.go | 1 + 16 files changed, 149 insertions(+), 87 deletions(-) diff --git a/metadata/utils.go b/metadata/utils.go index 8877faffb..b853af237 100644 --- a/metadata/utils.go +++ b/metadata/utils.go @@ -140,11 +140,14 @@ func GetMetadataProperty(props map[string]string, keys ...string) (val string, o // DecodeMetadata decodes metadata into a struct // This is an extension of mitchellh/mapstructure which also supports decoding durations func DecodeMetadata(input interface{}, result interface{}) error { - // avoids a common mistake of passing the metadata object, instead of the properties map - // if input is not of type map[string]string, then cast to metadata.Base and access the Properties - if _, ok := input.(map[string]string); !ok { - if base, ok := input.(Base); ok { - input = base.Properties + // avoids a common mistake of passing the metadata struct, instead of the properties map + // if input is of type struct, case it to metadata.Base and access the Properties instead + v := reflect.ValueOf(input) + if v.Kind() == reflect.Struct { + f := v.FieldByName("Properties") + if f.IsValid() && f.Kind() == reflect.Map { + properties := f.Interface().(map[string]string) + input = properties } } diff --git a/middleware/http/bearer/bearer_middleware.go b/middleware/http/bearer/bearer_middleware.go index 55eab7415..1d24b5a90 100644 --- a/middleware/http/bearer/bearer_middleware.go +++ b/middleware/http/bearer/bearer_middleware.go @@ -17,6 +17,7 @@ import ( "context" "fmt" "net/http" + "reflect" "strings" "time" @@ -25,6 +26,7 @@ import ( "github.com/lestrrat-go/jwx/v2/jwt" "github.com/dapr/components-contrib/internal/httputils" + contribMetadata "github.com/dapr/components-contrib/metadata" "github.com/dapr/components-contrib/middleware" "github.com/dapr/kit/logger" ) @@ -123,3 +125,10 @@ func (m *Middleware) GetHandler(ctx context.Context, metadata middleware.Metadat }) }, nil } + +func (m *Middleware) GetComponentMetadata() map[string]string { + metadataStruct := bearerMiddlewareMetadata{} + metadataInfo := map[string]string{} + contribMetadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/http/bearer/metadata.go b/middleware/http/bearer/metadata.go index 8430f7b65..7bf831201 100644 --- a/middleware/http/bearer/metadata.go +++ b/middleware/http/bearer/metadata.go @@ -29,19 +29,19 @@ import ( type bearerMiddlewareMetadata struct { // Issuer authority. - Issuer string `json:"issuer"` + Issuer string `json:"issuer" mapstructure:"issuer"` // Audience to expect in the token (usually, a client ID). - Audience string `json:"audience"` + Audience string `json:"audience" mapstructure:"audience"` // Optional address of the JKWS file. // If missing, will try to fetch the URL set in the OpenID Configuration document `/.well-known/openid-configuration`. - JWKSURL string `json:"jwksURL"` + JWKSURL string `json:"jwksURL" mapstructure:"jwksURL"` // Deprecated - use "issuer" instead. - IssuerURL string `json:"issuerURL"` + IssuerURL string `json:"issuerURL" mapstructure:"issuerURL"` // Deprecated - use "audience" instead. - ClientID string `json:"clientID"` + ClientID string `json:"clientID" mapstructure:"clientID"` // Internal properties - logger logger.Logger + logger logger.Logger `json:"-" mapstructure:"-"` } // Parse the component's metadata into the object. diff --git a/middleware/http/oauth2/oauth2_middleware.go b/middleware/http/oauth2/oauth2_middleware.go index e5d371c99..34f033f8a 100644 --- a/middleware/http/oauth2/oauth2_middleware.go +++ b/middleware/http/oauth2/oauth2_middleware.go @@ -17,6 +17,7 @@ import ( "context" "net/http" "net/url" + "reflect" "strings" "github.com/fasthttp-contrib/sessions" @@ -32,14 +33,14 @@ import ( // Metadata is the oAuth middleware config. type oAuth2MiddlewareMetadata struct { - ClientID string `json:"clientID"` - ClientSecret string `json:"clientSecret"` - Scopes string `json:"scopes"` - AuthURL string `json:"authURL"` - TokenURL string `json:"tokenURL"` - AuthHeaderName string `json:"authHeaderName"` - RedirectURL string `json:"redirectURL"` - ForceHTTPS string `json:"forceHTTPS"` + ClientID string `json:"clientID" mapstructure:"clientID"` + ClientSecret string `json:"clientSecret" mapstructure:"clientSecret"` + Scopes string `json:"scopes" mapstructure:"scopes"` + AuthURL string `json:"authURL" mapstructure:"authURL"` + TokenURL string `json:"tokenURL" mapstructure:"tokenURL"` + AuthHeaderName string `json:"authHeaderName" mapstructure:"authHeaderName"` + RedirectURL string `json:"redirectURL" mapstructure:"redirectURL"` + ForceHTTPS string `json:"forceHTTPS" mapstructure:"forceHTTPS"` } // NewOAuth2Middleware returns a new oAuth2 middleware. @@ -153,3 +154,10 @@ func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2Mid } return &middlewareMetadata, nil } + +func (m *Middleware) GetComponentMetadata() map[string]string { + metadataStruct := oAuth2MiddlewareMetadata{} + metadataInfo := map[string]string{} + mdutils.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware.go b/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware.go index a69d1000b..18da970a2 100644 --- a/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware.go +++ b/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware.go @@ -20,6 +20,7 @@ import ( "fmt" "net/http" "net/url" + "reflect" "strings" "time" @@ -34,13 +35,13 @@ import ( // Metadata is the oAuth clientcredentials middleware config. type oAuth2ClientCredentialsMiddlewareMetadata struct { - ClientID string `json:"clientID"` - ClientSecret string `json:"clientSecret"` - Scopes string `json:"scopes"` - TokenURL string `json:"tokenURL"` - HeaderName string `json:"headerName"` - EndpointParamsQuery string `json:"endpointParamsQuery,omitempty"` - AuthStyle int `json:"authStyle"` + ClientID string `json:"clientID" mapstructure:"clientID"` + ClientSecret string `json:"clientSecret" mapstructure:"clientSecret"` + Scopes string `json:"scopes" mapstructure:"scopes"` + TokenURL string `json:"tokenURL" mapstructure:"tokenURL"` + HeaderName string `json:"headerName" mapstructure:"headerName"` + EndpointParamsQuery string `json:"endpointParamsQuery,omitempty" mapstructure:"endpointParamsQuery"` + AuthStyle int `json:"authStyle" mapstructure:"authStyle"` } // TokenProviderInterface provides a common interface to Mock the Token retrieval in unit tests. @@ -176,3 +177,10 @@ func (m *Middleware) GetToken(ctx context.Context, conf *clientcredentials.Confi return tokenSource.Token() } + +func (m *Middleware) GetComponentMetadata() map[string]string { + metadataStruct := oAuth2ClientCredentialsMiddlewareMetadata{} + metadataInfo := map[string]string{} + mdutils.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware_test.go b/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware_test.go index c1ddae6d7..93ece76ee 100644 --- a/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware_test.go +++ b/middleware/http/oauth2clientcredentials/oauth2clientcredentials_middleware_test.go @@ -59,7 +59,7 @@ func TestOAuth2ClientCredentialsMetadata(t *testing.T) { "authStyle": "asdf", // This is the value to test } _, err2 := NewOAuth2ClientCredentialsMiddleware(log).GetHandler(context.Background(), metadata) - assert.EqualError(t, err2, "metadata errors: 1 error(s) decoding:\n\n* cannot parse 'AuthStyle' as int: strconv.ParseInt: parsing \"asdf\": invalid syntax") + assert.EqualError(t, err2, "metadata errors: 1 error(s) decoding:\n\n* cannot parse 'authStyle' as int: strconv.ParseInt: parsing \"asdf\": invalid syntax") // Invalid authStyle (int > 2) metadata.Properties["authStyle"] = "3" diff --git a/middleware/http/opa/middleware.go b/middleware/http/opa/middleware.go index 4c720859d..9a72a2ca5 100644 --- a/middleware/http/opa/middleware.go +++ b/middleware/http/opa/middleware.go @@ -23,6 +23,7 @@ import ( "math" "net/http" "net/textproto" + "reflect" "strconv" "strings" "time" @@ -32,6 +33,7 @@ import ( "github.com/dapr/components-contrib/internal/httputils" "github.com/dapr/components-contrib/internal/utils" + contribMetadata "github.com/dapr/components-contrib/metadata" "github.com/dapr/components-contrib/middleware" "github.com/dapr/kit/logger" ) @@ -39,11 +41,11 @@ import ( type Status int type middlewareMetadata struct { - Rego string `json:"rego"` - DefaultStatus Status `json:"defaultStatus,omitempty"` - IncludedHeaders string `json:"includedHeaders,omitempty"` - ReadBody string `json:"readBody,omitempty"` - includedHeadersParsed []string `json:"-"` + Rego string `json:"rego" mapstructure:"rego"` + DefaultStatus Status `json:"defaultStatus,omitempty" mapstructure:"defaultStatus"` + IncludedHeaders string `json:"includedHeaders,omitempty" mapstructure:"includedHeaders"` + ReadBody string `json:"readBody,omitempty" mapstructure:"readBody"` + internalIncludedHeadersParsed []string `json:"-" mapstructure:"-"` } // NewMiddleware returns a new Open Policy Agent middleware. @@ -136,7 +138,7 @@ func (m *Middleware) evalRequest(w http.ResponseWriter, r *http.Request, meta *m headers := map[string]string{} for key, value := range r.Header { - if len(value) > 0 && slices.Contains(meta.includedHeadersParsed, key) { + if len(value) > 0 && slices.Contains(meta.internalIncludedHeadersParsed, key) { headers[key] = strings.Join(value, ", ") } } @@ -232,29 +234,31 @@ func (m *Middleware) opaError(w http.ResponseWriter, meta *middlewareMetadata, e } func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*middlewareMetadata, error) { - b, err := json.Marshal(metadata.Properties) - if err != nil { - return nil, err - } - meta := middlewareMetadata{ DefaultStatus: 403, } - err = json.Unmarshal(b, &meta) + err := contribMetadata.DecodeMetadata(metadata.Properties, &meta) if err != nil { return nil, err } - meta.includedHeadersParsed = strings.Split(meta.IncludedHeaders, ",") + meta.internalIncludedHeadersParsed = strings.Split(meta.IncludedHeaders, ",") n := 0 - for i := range meta.includedHeadersParsed { - scrubbed := strings.ReplaceAll(meta.includedHeadersParsed[i], " ", "") + for i := range meta.internalIncludedHeadersParsed { + scrubbed := strings.ReplaceAll(meta.internalIncludedHeadersParsed[i], " ", "") if scrubbed != "" { - meta.includedHeadersParsed[n] = textproto.CanonicalMIMEHeaderKey(scrubbed) + meta.internalIncludedHeadersParsed[n] = textproto.CanonicalMIMEHeaderKey(scrubbed) n++ } } - meta.includedHeadersParsed = meta.includedHeadersParsed[:n] + meta.internalIncludedHeadersParsed = meta.internalIncludedHeadersParsed[:n] return &meta, nil } + +func (m *Middleware) GetComponentMetadata() map[string]string { + metadataStruct := middlewareMetadata{} + metadataInfo := map[string]string{} + contribMetadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/http/ratelimit/ratelimit_middleware.go b/middleware/http/ratelimit/ratelimit_middleware.go index 8638d2bfd..602d304fb 100644 --- a/middleware/http/ratelimit/ratelimit_middleware.go +++ b/middleware/http/ratelimit/ratelimit_middleware.go @@ -17,11 +17,12 @@ import ( "context" "fmt" "net/http" - "strconv" + "reflect" tollbooth "github.com/didip/tollbooth/v7" libstring "github.com/didip/tollbooth/v7/libstring" + contribMetadata "github.com/dapr/components-contrib/metadata" "github.com/dapr/components-contrib/middleware" "github.com/dapr/kit/logger" ) @@ -85,21 +86,24 @@ func (m *Middleware) GetHandler(_ context.Context, metadata middleware.Metadata) } func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*rateLimitMiddlewareMetadata, error) { - var middlewareMetadata rateLimitMiddlewareMetadata + middlewareMetadata := rateLimitMiddlewareMetadata{ + MaxRequestsPerSecond: defaultMaxRequestsPerSecond, + } + err := contribMetadata.DecodeMetadata(metadata.Properties, &middlewareMetadata) + if err != nil { + return nil, err + } - middlewareMetadata.MaxRequestsPerSecond = defaultMaxRequestsPerSecond - if val := metadata.Properties[maxRequestsPerSecondKey]; val != "" { - f, err := strconv.ParseFloat(val, 64) - if err != nil { - return nil, fmt.Errorf("error parsing metadata property %s: %w", maxRequestsPerSecondKey, err) - } - if f <= 0 { - return nil, fmt.Errorf("metadata property %s must be a positive value", maxRequestsPerSecondKey) - } - middlewareMetadata.MaxRequestsPerSecond = f - } else { - return nil, fmt.Errorf("metadata property %s must not be empty", maxRequestsPerSecondKey) + if middlewareMetadata.MaxRequestsPerSecond <= 0 { + return nil, fmt.Errorf("metadata property %s must be a positive value", maxRequestsPerSecondKey) } return &middlewareMetadata, nil } + +func (m *Middleware) GetComponentMetadata() map[string]string { + metadataStruct := rateLimitMiddlewareMetadata{} + metadataInfo := map[string]string{} + contribMetadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/http/ratelimit/ratelimit_middleware_test.go b/middleware/http/ratelimit/ratelimit_middleware_test.go index 784b3f938..2cd06a01a 100644 --- a/middleware/http/ratelimit/ratelimit_middleware_test.go +++ b/middleware/http/ratelimit/ratelimit_middleware_test.go @@ -26,13 +26,6 @@ import ( func TestMiddlewareGetNativeMetadata(t *testing.T) { m := &Middleware{} - t.Run(maxRequestsPerSecondKey+" is empty", func(t *testing.T) { - res, err := m.getNativeMetadata(middleware.Metadata{Base: metadata.Base{Properties: map[string]string{}}}) - require.Error(t, err) - assert.ErrorContains(t, err, "metadata property "+maxRequestsPerSecondKey+" must not be empty") - assert.Nil(t, res) - }) - t.Run(maxRequestsPerSecondKey+" is 0", func(t *testing.T) { res, err := m.getNativeMetadata(middleware.Metadata{Base: metadata.Base{Properties: map[string]string{ maxRequestsPerSecondKey: "0", @@ -56,7 +49,7 @@ func TestMiddlewareGetNativeMetadata(t *testing.T) { maxRequestsPerSecondKey: "foo-bar", }}}) require.Error(t, err) - assert.ErrorContains(t, err, "error parsing metadata property "+maxRequestsPerSecondKey) + assert.ErrorContains(t, err, "cannot parse 'MaxRequestsPerSecond' as float") assert.Nil(t, res) }) diff --git a/middleware/http/routeralias/routeralias_middleware.go b/middleware/http/routeralias/routeralias_middleware.go index 262c9ae43..23dc08e4d 100644 --- a/middleware/http/routeralias/routeralias_middleware.go +++ b/middleware/http/routeralias/routeralias_middleware.go @@ -88,3 +88,7 @@ func vars(r *http.Request) map[string]string { } return nil } + +func (m *Middleware) GetComponentMetadata() map[string]string { + return map[string]string{} +} diff --git a/middleware/http/routerchecker/routerchecker_middleware.go b/middleware/http/routerchecker/routerchecker_middleware.go index 244848a19..d80b1047a 100644 --- a/middleware/http/routerchecker/routerchecker_middleware.go +++ b/middleware/http/routerchecker/routerchecker_middleware.go @@ -17,6 +17,7 @@ import ( "context" "fmt" "net/http" + "reflect" "regexp" "github.com/dapr/components-contrib/internal/httputils" @@ -27,7 +28,7 @@ import ( // Metadata is the routerchecker middleware config. type Metadata struct { - Rule string `json:"rule"` + Rule string `json:"rule" mapstructure:"rule"` } // NewRouterCheckerMiddleware returns a new routerchecker middleware. @@ -72,3 +73,10 @@ func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*Metadata, } return &middlewareMetadata, nil } + +func (m *Middleware) GetComponentMetadata() map[string]string { + metadataStruct := Metadata{} + metadataInfo := map[string]string{} + mdutils.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/http/sentinel/middleware.go b/middleware/http/sentinel/middleware.go index cc761d8e2..a4b59f977 100644 --- a/middleware/http/sentinel/middleware.go +++ b/middleware/http/sentinel/middleware.go @@ -17,6 +17,7 @@ import ( "context" "fmt" "net/http" + "reflect" sentinel "github.com/alibaba/sentinel-golang/api" "github.com/alibaba/sentinel-golang/core/base" @@ -29,15 +30,15 @@ import ( ) type middlewareMetadata struct { - AppName string `json:"appName"` + AppName string `json:"appName" mapstructure:"appName"` // LogConfig - LogDir string `json:"logDir"` + LogDir string `json:"logDir" mapstructure:"logDir"` // Rules - FlowRules string `yaml:"flowRules"` - CircuitBreakerRules string `yaml:"circuitBreakerRules"` - HotSpotParamRules string `yaml:"hotSpotParamRules"` - IsolationRules string `yaml:"isolationRules"` - SystemRules string `yaml:"systemRules"` + FlowRules string `yaml:"flowRules" mapstructure:"flowRules"` + CircuitBreakerRules string `yaml:"circuitBreakerRules" mapstructure:"circuitBreakerRules"` + HotSpotParamRules string `yaml:"hotSpotParamRules" mapstructure:"hotSpotParamRules"` + IsolationRules string `yaml:"isolationRules" mapstructure:"isolationRules"` + SystemRules string `yaml:"systemRules" mapstructure:"systemRules"` } // NewMiddleware returns a new sentinel middleware. @@ -155,3 +156,10 @@ func getNativeMetadata(metadata middleware.Metadata) (*middlewareMetadata, error } return &md, nil } + +func (m *Middleware) GetComponentMetadata() map[string]string { + metadataStruct := middlewareMetadata{} + metadataInfo := map[string]string{} + mdutils.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/http/wasm/httpwasm.go b/middleware/http/wasm/httpwasm.go index 6b3a7fdca..2f5f11e47 100644 --- a/middleware/http/wasm/httpwasm.go +++ b/middleware/http/wasm/httpwasm.go @@ -4,11 +4,11 @@ import ( "bytes" "context" "crypto/rand" - "encoding/json" "errors" "fmt" "net/http" "os" + "reflect" "time" "github.com/http-wasm/http-wasm-host-go/handler" @@ -18,6 +18,7 @@ import ( "github.com/http-wasm/http-wasm-host-go/api" "github.com/tetratelabs/wazero" + mdutils "github.com/dapr/components-contrib/metadata" dapr "github.com/dapr/components-contrib/middleware" "github.com/dapr/kit/logger" ) @@ -31,10 +32,10 @@ import ( type middlewareMetadata struct { // Path is where to load a `%.wasm` file that implements the guest side of // the handler protocol. No default. - Path string `json:"path"` + Path string `json:"path" mapstructure:"path"` // guest is WebAssembly binary implementing the waPC guest, loaded from Path. - guest []byte + guest []byte `mapstructure:"-"` } type middleware struct { @@ -113,13 +114,8 @@ func (m *middleware) Log(_ context.Context, level api.LogLevel, message string) } func (m *middleware) getMetadata(metadata dapr.Metadata) (*middlewareMetadata, error) { - b, err := json.Marshal(metadata.Properties) - if err != nil { - return nil, err - } - - var data middlewareMetadata - err = json.Unmarshal(b, &data) + data := middlewareMetadata{} + err := mdutils.DecodeMetadata(metadata.Properties, &data) if err != nil { return nil, err } @@ -167,3 +163,10 @@ func (rh *requestHandler) Close() error { defer cancel() return rh.mw.Close(ctx) } + +func (m *middleware) GetComponentMetadata() map[string]string { + metadataStruct := middlewareMetadata{} + metadataInfo := map[string]string{} + mdutils.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} diff --git a/middleware/middleware.go b/middleware/middleware.go index 88e13660e..4e61da34f 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -21,4 +21,5 @@ import ( // Middleware is the interface for a middleware. type Middleware interface { GetHandler(ctx context.Context, metadata Metadata) (func(next http.Handler) http.Handler, error) + GetComponentMetadata() map[string]string } diff --git a/workflows/temporal/temporal.go b/workflows/temporal/temporal.go index c4168bd78..95fb731fd 100644 --- a/workflows/temporal/temporal.go +++ b/workflows/temporal/temporal.go @@ -17,6 +17,7 @@ import ( "context" "errors" "fmt" + "reflect" "time" "go.temporal.io/api/enums/v1" @@ -33,9 +34,9 @@ type TemporalWF struct { } type temporalMetadata struct { - Identity string `json:"identity"` - HostPort string `json:"hostport"` - Namespace string `json:"namespace"` + Identity string `json:"identity" mapstructure:"identity"` + HostPort string `json:"hostport" mapstructure:"hostport"` + Namespace string `json:"namespace" mapstructure:"namespace"` } // NewTemporalWorkflow returns a new workflow. @@ -139,6 +140,13 @@ func (c *TemporalWF) parseMetadata(meta workflows.Metadata) (*temporalMetadata, return &m, err } +func (c *TemporalWF) GetComponentMetadata() map[string]string { + metadataStruct := temporalMetadata{} + metadataInfo := map[string]string{} + metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo) + return metadataInfo +} + func lookupStatus(status enums.WorkflowExecutionStatus) string { switch status { case 0: diff --git a/workflows/workflow.go b/workflows/workflow.go index e47539dfa..e3f0d8388 100644 --- a/workflows/workflow.go +++ b/workflows/workflow.go @@ -22,4 +22,5 @@ type Workflow interface { Terminate(ctx context.Context, req *WorkflowReference) error Get(ctx context.Context, req *WorkflowReference) (*StateResponse, error) RaiseEvent(ctx context.Context, req *RaiseEventRequest) error + GetComponentMetadata() map[string]string }