Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update IntervalAction to use the common Address #536

Merged
merged 2 commits into from
Mar 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions v2/dtos/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ type RESTAddress struct {
HTTPMethod string `json:"httpMethod" validate:"required,oneof='GET' 'HEAD' 'POST' 'PUT' 'DELETE' 'TRACE' 'CONNECT'"`
}

func NewRESTAddress(host string, port int, httpMethod string) Address {
return Address{
Type: v2.REST,
Host: host,
Port: port,
RESTAddress: RESTAddress{
HTTPMethod: httpMethod,
},
}
}

type MQTTPubAddress struct {
Publisher string `json:"publisher" validate:"required"`
Topic string `json:"topic" validate:"required"`
Expand All @@ -60,6 +71,18 @@ type MQTTPubAddress struct {
ConnectTimeout int `json:"connectTimeout,omitempty"`
}

func NewMQTTAddress(host string, port int, publisher string, topic string) Address {
return Address{
Type: v2.MQTT,
Host: host,
Port: port,
MQTTPubAddress: MQTTPubAddress{
Publisher: publisher,
Topic: topic,
},
}
}

func ToAddressModel(a Address) models.Address {
var address models.Address

Expand Down
76 changes: 24 additions & 52 deletions v2/dtos/intervalaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,48 +8,40 @@ package dtos
import (
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/common"
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/models"

"github.com/google/uuid"
)

// IntervalAction and its properties are defined in the APIv2 specification:
// https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/support-scheduler/2.x#/IntervalAction
type IntervalAction struct {
common.Versionable `json:",inline"`
Created int64 `json:"created,omitempty"`
Modified int64 `json:"modified,omitempty"`
Id string `json:"id,omitempty" validate:"omitempty,uuid"`
Name string `json:"name" validate:"edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
IntervalName string `json:"intervalName" validate:"edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Protocol string `json:"protocol,omitempty"`
Host string `json:"host,omitempty"`
Port int `json:"port,omitempty"`
Path string `json:"path,omitempty"`
Parameters string `json:"parameters,omitempty"`
HTTPMethod string `json:"httpMethod,omitempty" validate:"omitempty,oneof='GET' 'HEAD' 'POST' 'PUT' 'DELETE' 'TRACE' 'CONNECT'"`
User string `json:"user,omitempty"`
Password string `json:"password,omitempty"`
Publisher string `json:"publisher,omitempty"`
Target string `json:"target" validate:"edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Topic string `json:"topic,omitempty"`
Created int64 `json:"created,omitempty"`
Modified int64 `json:"modified,omitempty"`
Id string `json:"id,omitempty" validate:"omitempty,uuid"`
Name string `json:"name" validate:"edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
IntervalName string `json:"intervalName" validate:"edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Address Address `json:"address" validate:"required"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the dive validation attribute to cause Address to be validated so don't have to manually call validate on Address??

Like we have done here for Readings in and Event:
https://github.com/edgexfoundry/go-mod-core-contracts/blob/master/v2/dtos/event.go#L30

Copy link
Member Author

@weichou1229 weichou1229 Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'dive' only works for slice and map, see https://pkg.go.dev/github.com/go-playground/validator/v10#hdr-Dive

In this case, the request DTO looks like:

  {
    "requestId": "e6e8a2f4-eb14-4649-9e2b-175247911369",
    "apiVersion":"v2",
    "action": {
        "apiVersion":"v2",
        "name": "query",
        "intervalName": "afternoon",
        "address":{
            "type": "REST",
            "host": "123.123.0.1",
            "port": 123,
            "httpMethod": "GET"
        }
            
    }
  }

Actually, I can success to verify the Address without call validation on the Address. But I need to verify the REST or MQTT protocol properties.
Currently, I didn't find any suitable tag for our use case so I wrote the Validate function, see https://github.com/edgexfoundry/go-mod-core-contracts/blob/master/v2/dtos/address.go#L25.

If we don't want to call validate on Address, we can

  1. Migrate the v1 validator to verify the deeper struct https://github.com/edgexfoundry/go-mod-core-contracts/blob/master/models/validator.go
  2. Or write a custom validation tag at https://github.com/edgexfoundry/go-mod-core-contracts/blob/master/v2/validator.go

}

func NewIntervalAction(name string, intervalName string, address Address) IntervalAction {
return IntervalAction{
Versionable: common.NewVersionable(),
Id: uuid.NewString(),
Name: name,
IntervalName: intervalName,
Address: address,
}
}

// UpdateIntervalAction and its properties are defined in the APIv2 specification:
// https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/support-scheduler/2.x#/UpdateIntervalAction
type UpdateIntervalAction struct {
common.Versionable `json:",inline"`
Id *string `json:"id" validate:"required_without=Name,edgex-dto-uuid"`
Name *string `json:"name" validate:"required_without=Id,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
IntervalName *string `json:"intervalName" validate:"edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Protocol *string `json:"protocol,omitempty"`
Host *string `json:"host,omitempty"`
Port *int `json:"port,omitempty"`
Path *string `json:"path,omitempty"`
Parameters *string `json:"parameters,omitempty"`
HTTPMethod *string `json:"httpMethod,omitempty" validate:"omitempty,oneof='GET' 'HEAD' 'POST' 'PUT' 'DELETE' 'TRACE' 'CONNECT'"`
User *string `json:"user,omitempty"`
Password *string `json:"password,omitempty"`
Publisher *string `json:"publisher,omitempty"`
Target *string `json:"target,omitempty" validate:"omitempty,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Topic *string `json:"topic,omitempty"`
Id *string `json:"id" validate:"required_without=Name,edgex-dto-uuid"`
Name *string `json:"name" validate:"required_without=Id,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
IntervalName *string `json:"intervalName" validate:"edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Address *Address `json:"address,omitempty"`
lenny-goodell marked this conversation as resolved.
Show resolved Hide resolved
}

// ToIntervalActionModel transforms the IntervalAction DTO to the IntervalAction Model
Expand All @@ -58,17 +50,7 @@ func ToIntervalActionModel(dto IntervalAction) models.IntervalAction {
model.Id = dto.Id
model.Name = dto.Name
model.IntervalName = dto.IntervalName
model.Protocol = dto.Protocol
model.Host = dto.Host
model.Port = dto.Port
model.Path = dto.Path
model.Parameters = dto.Parameters
model.HTTPMethod = dto.HTTPMethod
model.User = dto.User
model.Password = dto.Password
model.Publisher = dto.Publisher
model.Target = dto.Target
model.Topic = dto.Topic
model.Address = ToAddressModel(dto.Address)
return model
}

Expand All @@ -79,16 +61,6 @@ func FromIntervalActionModelToDTO(model models.IntervalAction) IntervalAction {
dto.Id = model.Id
dto.Name = model.Name
dto.IntervalName = model.IntervalName
dto.Protocol = model.Protocol
dto.Host = model.Host
dto.Port = model.Port
dto.Path = model.Path
dto.Parameters = model.Parameters
dto.HTTPMethod = model.HTTPMethod
dto.User = model.User
dto.Password = model.Password
dto.Publisher = model.Publisher
dto.Target = model.Target
dto.Topic = model.Topic
dto.Address = FromAddressModelToDTO(model.Address)
return dto
}
56 changes: 21 additions & 35 deletions v2/dtos/requests/intervalaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@ type AddIntervalActionRequest struct {
// Validate satisfies the Validator interface
func (request AddIntervalActionRequest) Validate() error {
err := v2.Validate(request)
return err
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
}
err = request.Action.Address.Validate()
lenny-goodell marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
}
return nil
}

// UnmarshalJSON implements the Unmarshaler interface for the AddIntervalActionRequest type
Expand All @@ -43,7 +50,7 @@ func (request *AddIntervalActionRequest) UnmarshalJSON(b []byte) error {

// validate AddIntervalActionRequest DTO
if err := request.Validate(); err != nil {
return err
return errors.NewCommonEdgeXWrapper(err)
}
return nil
}
Expand All @@ -68,7 +75,16 @@ type UpdateIntervalActionRequest struct {
// Validate satisfies the Validator interface
func (request UpdateIntervalActionRequest) Validate() error {
err := v2.Validate(request)
return err
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
}
if request.Action.Address != nil {
err = request.Action.Address.Validate()
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
}
}
lenny-goodell marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

// UnmarshalJSON implements the Unmarshaler interface for the UpdateIntervalActionRequest type
Expand All @@ -95,38 +111,8 @@ func ReplaceIntervalActionModelFieldsWithDTO(action *models.IntervalAction, patc
if patch.IntervalName != nil {
action.IntervalName = *patch.IntervalName
}
if patch.Protocol != nil {
action.Protocol = *patch.Protocol
}
if patch.Host != nil {
action.Host = *patch.Host
}
if patch.Port != nil {
action.Port = *patch.Port
}
if patch.Path != nil {
action.Path = *patch.Path
}
if patch.Parameters != nil {
action.Parameters = *patch.Parameters
}
if patch.HTTPMethod != nil {
action.HTTPMethod = *patch.HTTPMethod
}
if patch.User != nil {
action.User = *patch.User
}
if patch.Password != nil {
action.Password = *patch.Password
}
if patch.Publisher != nil {
action.Publisher = *patch.Publisher
}
if patch.Target != nil {
action.Target = *patch.Target
}
if patch.Topic != nil {
action.Topic = *patch.Topic
if patch.Address != nil {
action.Address = dtos.ToAddressModel(*patch.Address)
}
}

Expand Down
Loading