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

Migrate to new validation plugin #194

Merged
merged 27 commits into from
Mar 15, 2019
Merged

Migrate to new validation plugin #194

merged 27 commits into from
Mar 15, 2019

Conversation

rvolosatovs
Copy link
Contributor

@rvolosatovs rvolosatovs commented Feb 26, 2019

Summary:

Closes #69
Closes #51
Closes #260
References #245
References TheThingsIndustries/protoc-gen-fieldmask#22 TheThingsIndustries/protoc-gen-fieldmask#24 TheThingsIndustries/protoc-gen-fieldmask#25 TheThingsIndustries/protoc-gen-fieldmask#26

Changes:

@rvolosatovs rvolosatovs added the compat/api This could affect API compatibility label Feb 26, 2019
@rvolosatovs rvolosatovs added this to the February 2019 milestone Feb 26, 2019
@rvolosatovs rvolosatovs self-assigned this Feb 26, 2019
@rvolosatovs rvolosatovs force-pushed the feature/51-validation branch 2 times, most recently from 2b57a22 to eac2172 Compare February 26, 2019 17:53
@rvolosatovs rvolosatovs requested review from johanstokking and removed request for KrishnaIyer February 28, 2019 12:59
@johanstokking johanstokking requested review from htdvisser and removed request for johanstokking February 28, 2019 13:03
pkg/rpcmiddleware/validator/validator.go Outdated Show resolved Hide resolved
pkg/rpcmiddleware/validator/validator_test.go Outdated Show resolved Hide resolved
"application_ids",
"field_mask",
}
var ListApplicationsRequestFieldPathsNested = []string{
Copy link
Contributor

Choose a reason for hiding this comment

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

Inconsistent spacing, but that can be fixed in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

switch name {
case "ids":

if v, ok := interface{}(&m.ApplicationIdentifiers).(interface{ ValidateFields(...string) error }); ok {
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks pretty dirty and I'm not sure the compiler optimizes this, but we can leave it for a future PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IDEM, see #194 (comment)

cause)
}

var _ error = ApplicationsValidationError{}
Copy link
Contributor

Choose a reason for hiding this comment

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

These kind of assertions belong in test code (same below). For every XXXValidationError we initialize two, each taking up 32 bytes of memory (or so). Do we really need to generate them? Can't we just add a unit test in the generator to make sure that (any) generated XXXValidationError implements these?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IDEM, see #194 (comment)

Copy link
Contributor

@htdvisser htdvisser left a comment

Choose a reason for hiding this comment

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

Looks good to me now, but let's test CLI and e2e join/uplink/downlink flow before merging.

@rvolosatovs
Copy link
Contributor Author

rvolosatovs commented Feb 28, 2019

@adriansmares can you test these changes ?
This is not as simple as it seems and won't work directly as it is now

@htdvisser htdvisser modified the milestones: February 2019, March 2019 Feb 28, 2019
@rvolosatovs rvolosatovs force-pushed the feature/51-validation branch from 0c411af to 712efad Compare March 5, 2019 23:04
@rvolosatovs rvolosatovs requested a review from htdvisser March 5, 2019 23:05
@rvolosatovs rvolosatovs added the needs/discussion We need to discuss this label Mar 5, 2019
@rvolosatovs
Copy link
Contributor Author

rvolosatovs commented Mar 5, 2019

Giving it another thought, it only makes sense to have a ValidateFields(...string) error(or Validate(...string) error on proto message types.
Should we support both Validate() error and ValidateFields(...string) error signatures?
What do you think about this:
The Validate() error would be generated for non-message types, same as it's done by all other validator generators, however ValidateFields(...string) error would only be generated for message types.
The generated validators would assert Validate() error for non-message and non-custom types, in all other cases they would first try ValidateFields(...string) error and then Validate() error in a type switch

In fact, for any non-generated go struct it does not make sense to accept fieldpaths as parameters, e.g.:

func (fp FrequencyPlan) Validate() error {

Since there are no proto paths defined for the struct.
In result we just end up with a confusing method signature and additional error handling for all these cases, where fieldpath cannot be specified.

@johanstokking @htdvisser

@johanstokking
Copy link
Member

johanstokking commented Mar 6, 2019

This would mean that ValidateFields() comes instead of Validate() in the interceptor?

I think this could come in handy indeed. I would also see this useful in the registry, where we do want to validate (#70) but where we don't have the means to do so. Sure, with our proto stores we have access to the entire entity, but we don't when working with IoT platform device registries.

@rvolosatovs
Copy link
Contributor Author

rvolosatovs commented Mar 6, 2019

Not "instead". The proposal is this ordering - https://github.com/rvolosatovs/lorawan-stack/blob/a761c089c3d176d85bdb9783423d46afbd5707eb/pkg/rpcmiddleware/validator/validator.go#L91-L112

The validator plugin generates ValidateFields(...string) error only for entities, for which fieldpaths can be passed(proto message types), for everything else it generates Validate() error. That means that validators for non-proto types are also Validate() error
In fact message types could still have Validate() error, which would simply be msg.ValidateFields(), since by default we validate all fields

@htdvisser
Copy link
Contributor

htdvisser commented Mar 6, 2019

I think we should not change the interceptor (so it still calls ValidateContext(ctx) error or Validate() error if the former doesn't exist).

On all request messages we implement (by hand) a ValidateContext(ctx) that calls ValidateFields(...) error with the appropriate field mask paths if needed. For instance, on UpdateXXXRequest messages it calls msg.XXX.ValidateFields(msg.FieldMask.Paths...), but on GetXXXRequest messages we can ignore the field mask and only validate the fields of GetXXXRequest.

No need to change what is generated.

@rvolosatovs
Copy link
Contributor Author

I think that works. In registries we then simply call ValidateFields directly.

@rvolosatovs rvolosatovs force-pushed the feature/51-validation branch from 712efad to 97f87aa Compare March 6, 2019 11:18
@rvolosatovs
Copy link
Contributor Author

I made the changes, please take a look.
We still need to support ValidateFields in interceptor, since for the messages not containing the fieldmask we need to validate all fields anyway and they don't have Validate or ValidateContext defined

@htdvisser
Copy link
Contributor

LGTM.

Next is to implement Validate/ValidateContext on UpdateXXXRequest and similar messages and to test everything.

@rvolosatovs rvolosatovs added the blocking Another issue or pull request is waiting for this label Mar 6, 2019
@rvolosatovs rvolosatovs force-pushed the feature/51-validation branch from e599a3c to 7d0d128 Compare March 15, 2019 11:50
@rvolosatovs
Copy link
Contributor Author

@adriansmares Can you test this?
I tried OTAA join/uplink/downlink with Class C, but more thorough testing could be useful here

Copy link
Member

@johanstokking johanstokking left a comment

Choose a reason for hiding this comment

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

Wait for regression testing confirmation by @adriansmares

Copy link
Contributor

@adriansmares adriansmares left a comment

Choose a reason for hiding this comment

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

Approved. Both OTAA and ABP tests are working correctly.

@rvolosatovs rvolosatovs merged commit 126017d into master Mar 15, 2019
@rvolosatovs rvolosatovs deleted the feature/51-validation branch March 15, 2019 13:40
@htdvisser htdvisser mentioned this pull request Apr 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocking release This is blocking a release blocking Another issue or pull request is waiting for this compat/api This could affect API compatibility
Projects
None yet
4 participants