Skip to content

Commit

Permalink
Fixes #43 - Upgrade Go SDK to spec 0.7 (#43)
Browse files Browse the repository at this point in the history
* Upgrade to spec 0.7: SpecVersion, Secrets, Constants, Annotations and DataInputSchema

Signed-off-by: Ricardo Zanini <zanini@redhat.com>

* Fix formatting

Signed-off-by: Ricardo Zanini <zanini@redhat.com>

* FunctionTypes, Errors, SubFlowRef, Auth, Timeouts

Signed-off-by: Ricardo Zanini <zanini@redhat.com>

* Auth, Timeouts, Review states, functions

Signed-off-by: Ricardo Zanini <zanini@redhat.com>

* Adding basic validation test for every workflow

Signed-off-by: Ricardo Zanini <zanini@redhat.com>

* Update README

Signed-off-by: Ricardo Zanini <zanini@redhat.com>
  • Loading branch information
ricardozanini authored Oct 1, 2021
1 parent 4362a26 commit a1c8b1d
Show file tree
Hide file tree
Showing 33 changed files with 1,399 additions and 223 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Current status of features implemented in the SDK is listed in the table below:
| Latest Releases | Conformance to spec version |
| :---: | :---: |
| [v1.0.0](https://github.com/serverlessworkflow/sdk-go/releases/tag/v1.0.0) | [v0.5](https://github.com/serverlessworkflow/specification/tree/0.5.x) |
| [v2.0.1](https://github.com/serverlessworkflow/sdk-go/releases/tag/v2.0.0) | [v0.6](https://github.com/serverlessworkflow/specification/tree/0.6.x) |
| [v2.0.1](https://github.com/serverlessworkflow/sdk-go/releases/tag/v2.0.1) | [v0.6](https://github.com/serverlessworkflow/specification/tree/0.6.x) |
| [v2.1.0](https://github.com/serverlessworkflow/sdk-go/releases/tag/v2.1.0) | [v0.7](https://github.com/serverlessworkflow/specification/tree/0.7.x) |

## How to use

Expand Down
276 changes: 276 additions & 0 deletions model/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
// Copyright 2021 The Serverless Workflow Specification Authors
//
// 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 model

import (
"encoding/json"
"fmt"
)

// AuthType ...
type AuthType string

const (
// AuthTypeBasic ...
AuthTypeBasic AuthType = "basic"
// AuthTypeBearer ...
AuthTypeBearer AuthType = "bearer"
// AuthTypeOAuth2 ...
AuthTypeOAuth2 AuthType = "oauth2"
)

// GrantType ...
type GrantType string

const (
// GrantTypePassword ...
GrantTypePassword GrantType = "password"
// GrantTypeClientCredentials ...
GrantTypeClientCredentials GrantType = "clientCredentials"
// GrantTypeTokenExchange ...
GrantTypeTokenExchange GrantType = "tokenExchange"
)

// authTypesMapping map to support JSON unmarshalling when guessing the auth scheme
var authTypesMapping = map[AuthType]AuthProperties{
AuthTypeBasic: &BasicAuthProperties{},
AuthTypeBearer: &BearerAuthProperties{},
AuthTypeOAuth2: &OAuth2AuthProperties{},
}

// Auth ...
type Auth struct {
// Name Unique auth definition name
Name string `json:"name" validate:"required"`
// Scheme Defines the auth type
Scheme AuthType `json:"scheme,omitempty" validate:"omitempty,min=1"`
// Properties ...
Properties AuthProperties `json:"properties" validate:"required"`
}

// UnmarshalJSON ...
func (a *Auth) UnmarshalJSON(data []byte) error {
auth := make(map[string]json.RawMessage)
if err := json.Unmarshal(data, &auth); err != nil {
// it's a file
file, err := unmarshalFile(data)
if err != nil {
return err
}
// call us recursively
if err := json.Unmarshal(file, &a); err != nil {
return err
}
return nil
}
if err := unmarshalKey("scheme", auth, &a.Scheme); err != nil {
return err
}
if err := unmarshalKey("name", auth, &a.Name); err != nil {
return err
}

if len(a.Scheme) == 0 {
a.Scheme = AuthTypeBasic
}
if _, ok := authTypesMapping[a.Scheme]; !ok {
return fmt.Errorf("authentication scheme %s not supported", authTypesMapping["type"])
}
// we take the type we want to unmarshal based on the scheme
authProperties := authTypesMapping[a.Scheme]
if err := unmarshalKey("properties", auth, authProperties); err != nil {
return err
}
return nil
}

// AuthProperties ...
type AuthProperties interface {
// GetMetadata ...
GetMetadata() *Metadata
// GetSecret ...
GetSecret() string
}

// BaseAuthProperties ...
type BaseAuthProperties struct {
Common
// Secret Expression referencing a workflow secret that contains all needed auth info
Secret string `json:"secret,omitempty"`
}

// UnmarshalJSON ...
func (b *BaseAuthProperties) UnmarshalJSON(data []byte) error {
properties := make(map[string]json.RawMessage)
if err := json.Unmarshal(data, &properties); err != nil {
b.Secret, err = unmarshalString(data)
if err != nil {
return err
}
return nil
}
if err := unmarshalKey("metadata", properties, &b.Metadata); err != nil {
return err
}
if err := unmarshalKey("secret", properties, &b.Secret); err != nil {
return err
}
return nil
}

// GetMetadata ...
func (b *BaseAuthProperties) GetMetadata() *Metadata {
return &b.Metadata
}

// GetSecret ...
func (b *BaseAuthProperties) GetSecret() string {
return b.Secret
}

// BasicAuthProperties Basic Auth Info
type BasicAuthProperties struct {
BaseAuthProperties
// Username String or a workflow expression. Contains the username
Username string `json:"username" validate:"required"`
// Password String or a workflow expression. Contains the user password
Password string `json:"password" validate:"required"`
}

// UnmarshalJSON ...
func (b *BasicAuthProperties) UnmarshalJSON(data []byte) error {
properties := make(map[string]json.RawMessage)
if err := json.Unmarshal(data, &properties); err != nil {
err = json.Unmarshal(data, &b.BaseAuthProperties)
if err != nil {
return err
}
return nil
}
if err := unmarshalKey("username", properties, &b.Username); err != nil {
return err
}
if err := unmarshalKey("password", properties, &b.Password); err != nil {
return err
}
if err := unmarshalKey("metadata", properties, &b.Metadata); err != nil {
return err
}
return nil
}

// BearerAuthProperties Bearer auth information
type BearerAuthProperties struct {
BaseAuthProperties
// Token String or a workflow expression. Contains the token
Token string `json:"token" validate:"required"`
}

// UnmarshalJSON ...
func (b *BearerAuthProperties) UnmarshalJSON(data []byte) error {
properties := make(map[string]json.RawMessage)
if err := json.Unmarshal(data, &properties); err != nil {
err = json.Unmarshal(data, &b.BaseAuthProperties)
if err != nil {
return err
}
return nil
}
if err := unmarshalKey("token", properties, &b.Token); err != nil {
return err
}
if err := unmarshalKey("metadata", properties, &b.Metadata); err != nil {
return err
}
return nil
}

// OAuth2AuthProperties OAuth2 information
type OAuth2AuthProperties struct {
BaseAuthProperties
// Authority String or a workflow expression. Contains the authority information
Authority string `json:"authority,omitempty" validate:"omitempty,min=1"`
// GrantType Defines the grant type
GrantType GrantType `json:"grantType" validate:"required"`
// ClientID String or a workflow expression. Contains the client identifier
ClientID string `json:"clientId" validate:"required"`
// ClientSecret Workflow secret or a workflow expression. Contains the client secret
ClientSecret string `json:"clientSecret,omitempty" validate:"omitempty,min=1"`
// Scopes Array containing strings or workflow expressions. Contains the OAuth2 scopes
Scopes []string `json:"scopes,omitempty" validate:"omitempty,min=1"`
// Username String or a workflow expression. Contains the username. Used only if grantType is 'resourceOwner'
Username string `json:"username,omitempty" validate:"omitempty,min=1"`
// Password String or a workflow expression. Contains the user password. Used only if grantType is 'resourceOwner'
Password string `json:"password,omitempty" validate:"omitempty,min=1"`
// Audiences Array containing strings or workflow expressions. Contains the OAuth2 audiences
Audiences []string `json:"audiences,omitempty" validate:"omitempty,min=1"`
// SubjectToken String or a workflow expression. Contains the subject token
SubjectToken string `json:"subjectToken,omitempty" validate:"omitempty,min=1"`
// RequestedSubject String or a workflow expression. Contains the requested subject
RequestedSubject string `json:"requestedSubject,omitempty" validate:"omitempty,min=1"`
// RequestedIssuer String or a workflow expression. Contains the requested issuer
RequestedIssuer string `json:"requestedIssuer,omitempty" validate:"omitempty,min=1"`
}

// TODO: use reflection to unmarshal the keys and think on a generic approach to handle them

// UnmarshalJSON ...
func (b *OAuth2AuthProperties) UnmarshalJSON(data []byte) error {
properties := make(map[string]json.RawMessage)
if err := json.Unmarshal(data, &properties); err != nil {
err = json.Unmarshal(data, &b.BaseAuthProperties)
if err != nil {
return err
}
return nil
}
if err := unmarshalKey("authority", properties, &b.Authority); err != nil {
return err
}
if err := unmarshalKey("grantType", properties, &b.GrantType); err != nil {
return err
}
if err := unmarshalKey("clientId", properties, &b.ClientID); err != nil {
return err
}
if err := unmarshalKey("clientSecret", properties, &b.ClientSecret); err != nil {
return err
}
if err := unmarshalKey("scopes", properties, &b.Scopes); err != nil {
return err
}
if err := unmarshalKey("username", properties, &b.Username); err != nil {
return err
}
if err := unmarshalKey("password", properties, &b.Password); err != nil {
return err
}
if err := unmarshalKey("audiences", properties, &b.Audiences); err != nil {
return err
}
if err := unmarshalKey("subjectToken", properties, &b.SubjectToken); err != nil {
return err
}
if err := unmarshalKey("requestedSubject", properties, &b.RequestedSubject); err != nil {
return err
}
if err := unmarshalKey("requestedIssuer", properties, &b.RequestedIssuer); err != nil {
return err
}
if err := unmarshalKey("metadata", properties, &b.Metadata); err != nil {
return err
}
return nil
}
10 changes: 2 additions & 8 deletions model/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ type Event struct {
Type string `json:"type" validate:"required"`
// Defines the CloudEvent as either 'consumed' or 'produced' by the workflow. Default is 'consumed'
Kind EventKind `json:"kind,omitempty"`
// If `true`, only the Event payload is accessible to consuming Workflow states. If `false`, both event payload and context attributes should be accessible"
DataOnly bool `json:"dataOnly,omitempty"`
// CloudEvent correlation definitions
Correlation []Correlation `json:"correlation,omitempty" validate:"omitempty,dive"`
}
Expand All @@ -79,11 +81,3 @@ type EventRef struct {
// Add additional extension context attributes to the produced event
ContextAttributes map[string]interface{} `json:"contextAttributes,omitempty"`
}

// SubFlowRef ...
type SubFlowRef struct {
// Sub-workflow unique id
WorkflowID string `json:"workflowId" validate:"required"`
// Sub-workflow version
Version string `json:"version,omitempty"`
}
6 changes: 6 additions & 0 deletions model/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const (
FunctionTypeExpression FunctionType = "expression"
// FunctionTypeGraphQL ...
FunctionTypeGraphQL FunctionType = "graphql"
// FunctionTypeAsyncAPI ...
FunctionTypeAsyncAPI FunctionType = "asyncapi"
// FunctionTypeOData ...
FunctionTypeOData FunctionType = "odata"
)

// FunctionType ...
Expand All @@ -39,6 +43,8 @@ type Function struct {
Operation string `json:"operation" validate:"required"`
// Defines the function type. Is either `rest`, `rpc`, `expression` or `graphql`. Default is `rest`
Type FunctionType `json:"type,omitempty"`
// References an auth definition name to be used to access to resource defined in the operation parameter
AuthRef string `json:"authRef,omitempty" validate:"omitempty,min=1"`
}

// FunctionRef ...
Expand Down
2 changes: 1 addition & 1 deletion model/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type Retry struct {
// Numeric value, if specified the delay between retries is multiplied by this value.
Multiplier floatstr.Float32OrString `json:"multiplier,omitempty" validate:"omitempty,min=0"`
// Maximum number of retry attempts.
MaxAttempts intstr.IntOrString `json:"maxAttempts" validate:"required,min=0"`
MaxAttempts intstr.IntOrString `json:"maxAttempts" validate:"required"`
// If float type, maximum amount of random time added or subtracted from the delay between each retry relative to total delay (between 0 and 1). If string type, absolute maximum amount of random time added or subtracted from the delay between each retry (ISO 8601 duration format)
Jitter floatstr.Float32OrString `json:"jitter,omitempty" validate:"omitempty,min=0,max=1"`
}
Loading

0 comments on commit a1c8b1d

Please sign in to comment.