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

Validate JSON properties with relative-path format #83

Merged
merged 5 commits into from
Nov 19, 2020

Conversation

mtojek
Copy link
Contributor

@mtojek mtojek commented Nov 16, 2020

We decided to proceed with mutex and FormatCheckers. I've adjusted the PR. The solution should thread-safe (but uses locking).


I'm opening this as draft to discuss possible design ideas.

Resolves: #31

I found FormatCheckers in gojsonschema that could be used to verify properties with relative paths (screenshot and image src). Unfortunately the FormatCheckers is a global object, not thread-safe and can be applied only to statics.

For reference:
xeipuuv/gojsonschema#257
xeipuuv/gojsonschema#300

I'm wondering whether we should guard the piece of code with Validate() and refreshFormatCheckersContext with a mutex or should we use a different approach:

  1. Package domain-aware validation (screenshots and images have sources). So far we didn't need to strongly depend on package domain and it would be nice not to follow this path
  2. Fork the package and modify the existing JSON schema draft (to support type: string & subType: relative-path.
    See:
    http://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7
    http://json-schema.org/draft/2019-09/release-notes.html#format-vocabulary
  3. Depend on fork: Local Format Checker xeipuuv/gojsonschema#256

My opinion:

I wouldn't like to implement the new entire schema loader that focuses only on sub-type (path). KISS approach: define type-based Go validation functions (compiled into the validator). So far we need to apply them only to package manifests (Image type).

@mtojek mtojek marked this pull request as draft November 16, 2020 19:20
@elasticmachine
Copy link

elasticmachine commented Nov 16, 2020

💚 Build Succeeded

the below badges are clickable and redirect to their specific view in the CI or DOCS
Pipeline View Test View Changes Artifacts preview

Expand to view the summary

Build stats

  • Build Cause: [Pull request #83 updated]

  • Start Time: 2020-11-19T08:10:08.385+0000

  • Duration: 2 min 13 sec

@ycombinator
Copy link
Contributor

Yeah, I'm in favor of KISS. What you have here is fine for now (I realize it's not threadsafe). We can worry about that when it starts to become an issue.

@@ -93,3 +94,9 @@ func (s *folderItemSpec) validate(fs http.FileSystem, folderSpecPath string, ite
}
return errs
}

func refreshFormatCheckersContext(currentPath string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that this is a global instruction, should we just move it into init to make that more explicit/obvious? It will also guarantee that the relative-path format checker is initialized exactly once at package initialization time.

Copy link
Contributor Author

@mtojek mtojek Nov 17, 2020

Choose a reason for hiding this comment

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

Let me describe the case here:

The method refreshFormatCheckersContext is called just before calling Validate to modify the global state every time it's executed against a package, because there is no way to sneak a context (with a package path).

Also, we start depending on the format property, which is not the exact case here as we don't verify the format only, but also checks the existing path. In case of an error the library fails with a generic error that the format is not correct.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah yes, of course! I totally missed the currentPath argument 🤦.

Okay, I understand what's going on here now and why you have to do it this way. This is good as-is but I made a related comment at the location where this function is being called from.

@@ -78,6 +78,7 @@ func (s *folderItemSpec) validate(fs http.FileSystem, folderSpecPath string, ite

// validation with schema
documentLoader := gojsonschema.NewBytesLoader(itemData)
refreshFormatCheckersContext(filepath.Dir(itemPath))
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that we are essentially creating a new custom format checker for every filepath.Dir(itemPath), perhaps we should also remove this format checker using defer gojsonschema.FormatCheckers.Remove(...)?

Additionally I would add a comment here noting that this call is not thread-safe so, in the future, if we need to introduce concurrency within a single elastic-package lint invocation, we can add mutexes here or something like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can add a mutex to surround this place, but it's just mitigation.

Just wanted to make sure that we understand the risk and consequences here (incl. error messages).

Copy link
Contributor

Choose a reason for hiding this comment

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

Up to you if you want to add the mutex now or later. I don't think it's going to make much of a performance difference to have it now itself but if you want to KISS feel free to leave it out until we need it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, it wasn't hard to add the mutex, so I did it. I've also adjusted the error message.

@mtojek mtojek self-assigned this Nov 17, 2020
@mtojek mtojek marked this pull request as ready for review November 17, 2020 11:59
}
return errs
}

func loadRelativePathFormatChecker(currentPath string) {
gojsonschema.FormatCheckers.Add("relative-path", RelativePathChecker{
Copy link
Contributor

@ycombinator ycombinator Nov 18, 2020

Choose a reason for hiding this comment

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

Consider making relative-path a constant, now that we are using it in a few places in code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@@ -114,6 +114,7 @@ spec:
src:
description: Relative path to the icon's image file.
type: string
format: relative-path
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be documented in CONTRIBUTING.md for anyone who wants to add elements to the spec in the future that could use relative-path validation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

Currently, the following custom formats are available:

* `relative-path`: Relative path to the package root directory. The format checker verifies if the path is correct and
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it relative to the package root directory or is it relative to where the folder item spec file is defined?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is relative to the package root (as noted).

Copy link
Contributor

@ycombinator ycombinator left a comment

Choose a reason for hiding this comment

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

LGTM.

@mtojek mtojek merged commit 49ecd87 into elastic:master Nov 19, 2020
rw-access pushed a commit to rw-access/package-spec that referenced this pull request Mar 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Validate the icon and screenshot sources exist
3 participants