-
Notifications
You must be signed in to change notification settings - Fork 72
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
Conversation
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
} | ||
return errs | ||
} | ||
|
||
func loadRelativePathFormatChecker(currentPath string) { | ||
gojsonschema.FormatCheckers.Add("relative-path", RelativePathChecker{ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
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
ingojsonschema
that could be used to verify properties with relative paths (screenshot and image src). Unfortunately theFormatCheckers
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()
andrefreshFormatCheckersContext
with a mutex or should we use a different approach: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
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).