-
Notifications
You must be signed in to change notification settings - Fork 801
verbose output object digest in validate #234
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
Conversation
|
ping @s-urbaniak ,@opencontainers/image-spec-maintainers, PTAL thank lots! |
cmd/oci-image-tool/validate.go
Outdated
|
|
||
| cmd.Flags().BoolVar( | ||
| &v.verbose, "verbose", false, | ||
| fmt.Sprintf(`output format to validate. If unset, oci-image-tool will only output a OK or failed result.`), |
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.
what does it mean "output format to validate*? Should we also have -v?
|
@xiekeyang I tried this and it's only outputting the digest of the config in an imageLayout: I have a branch ( My branch also contains fixes for the other point in #222. |
cmd/oci-image-tool/validate.go
Outdated
| defer f.Close() | ||
|
|
||
| if v.verbose { | ||
| fd, err := os.Open(name) |
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 doesn't seem the right place to re-open the file just to get its digest, I would have done this inside each validation func (and as already explained, on every object being validated)
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.
@runcom , @s-urbaniak , here I've some confusion point:
for imageLayout and image type, the digests are calculated and I can collect and output them directly. In these 2 cases, it is meaningful to verbose output the digests which validate the consistency.
However, for manifest, manifestList and config type, I didn't find the digest calculation. Meantime, I think it needn't to output the digest because it just validate the simple file's json schema that is not relevant consistency.
So, my suggestion is just output digests for imageLayout and image type, and output nothing for manifest, manifestList and config type.
What is your proposal? THanks a lot!
|
@runcom Thanks for your review!
Here I made inaccuracy to output only one digest for all that validate-config validate-manifest and validate-imageLayout case.
I read your branch. It seems my commit doesn't seriously conflict to your branch yet. May I fix my commit here, according to your proposal? |
|
Yes, please go ahead and fix this here :) |
|
WIP |
|
@runcom , @s-urbaniak , here I've some confusion point: for imageLayout and image type, the digests are calculated and I can collect and output them directly. In these 2 cases, it is meaningful to verbose output the digests which validate the consistency. However, for manifest, manifestList and config type, I didn't find the digest calculation. Meantime, I think it needn't to output the digest because it just validate the simple file's json schema that is not relevant consistency. So, my suggestion is just output digests for imageLayout and image type, and output nothing for manifest, manifestList and config type. What is your proposal? Thanks a lot! |
|
It you hash a manifest, manifest list or config you get their digests, why not calculate and print them? @s-urbaniak wdyt? |
|
@runcom @s-urbaniak |
|
Additional, for manifest, manifest list or config case, the digest doesn't exist yet, which we should calculate for only print purpose. Is that a less meaningful way and will impact the program performance? right? |
cmd/oci-image-tool/validate.go
Outdated
| if typ == "" { | ||
| if typ, err = autodetect(name); err != nil { | ||
| return errors.Wrap(err, "unable to determine type") | ||
| return []string{}, errors.Wrap(err, "unable to determine type") |
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.
return nil, errors.Wrap...
|
@xiekeyang @runcom verbose mode could imply additional computational overhead, I'd be fine with also printing the digests if being in verbose mode, so users have more insight. @xiekeyang The |
|
It is finished, PTAL. |
|
PTAL |
| cmd.Flags().BoolVarP( | ||
| &v.verbose, "verbose", "v", false, | ||
| fmt.Sprintf(`Output verbosely, including all objects digest to be validated. If unset, oci-image-tool will only output a OK or failed result.`), | ||
| ) |
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.
Ocitools uses logrus and --log-level (e.g. see opencontainers/runtime-tools#97). I'd recommend we go that route instead of carrying a verbose boolean around with us.
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 doesn't really seem to be log output. This is program output.
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.
@stevvooe I also find that log and fmt are both used in program. Do we need to unite them by log, or keep the previous state?
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.
@xiekeyang You don't unite these. Logging and output are different things. Typically, logging provides hints at how a program is doing, whereas the output is the primary purpose of the program.
Under a verbose flag, I would expect that to affect primary program output and not really have anything to do with logs, although this varies in practice.
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.
On Thu, Sep 08, 2016 at 08:56:40PM -0700, Stephen Day wrote:
- cmd.Flags().BoolVarP(
&v.verbose, "verbose", "v", false,fmt.Sprintf(`Output verbosely, including all objects digest to be validated. If unset, oci-image-tool will only output a OK or failed result.`),- )
@xiekeyang You don't unite these. Logging and output are different
things. Typically, logging provides hints at how a program is doing,
whereas the output is the primary purpose of the program.
I agree with this.
Under a verbose flag, I would expect that to affect primary program
output and not really have anything to do with logs, although this
varies in practice.
This is surprising to me. For example, ‘cp -v …’ prints hints about
what the program is doing. Printing:
‘x’ -> ‘y’
is not the primary goal of the command (which is copying the files,
and not about writing anything to stdio). Can you point to an example
where --verbose affects the primary program output?
In this case, the goal of the program is to validate a ref. I expect
the primary purpose of the program is to output those PASS/FAIL test
results (e.g. in TAP 1, although we aren't using TAP here, more's
the pity ;). A --verbose or --log-level option should have no effect
on that test output. What it should do is adjust the log verbosity,
so we get information about the tests as they're being carried out.
This PR (as it stands with 4badd20) is sitting somewhere in the
middle. If the digest being validated is a log output (which I think
it should be), it should be covered by --verbose or --log-level and
printed to stderr when we start validating it (4badd20 collects
digests and prints them after the test passes). If the digest being
validated is part of the primary program output, we don't need
--verbose or --log-level, and should be printing it to stdout as a
sub-test of the ref validation. In TAP, that would look like:
TAP version 13
ok 1 - manifest.v1+json sha256:abc…
ok 2 - layer.tar+gzip sha256:def…
ok 3 - ref v1 (sha256:abc…)
ok 4 - manifest.v1+json sha256:123…
ok 5 - layer.tar+gzip sha256:456…
ok 6 - ref v2 (sha256:123…)
1..6
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.
@wking I'm sure you can find exceptions to my generalizations. :)
For our purposes, I would expect log level changes to provide more information about what is happening, while an increase in verbosity would provide richer test output.
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.
On Fri, Sep 09, 2016 at 02:43:03PM -0700, Stephen Day wrote:
… while an increase in verbosity would provide richer test output.
What is “richer test output”? Shouldn't we always run as many tests
as we have code for and leave it to TAP harnesses and such to distill
the data (if the user wants it distilled) 1?
|
Actually I prefer to |
schema/validator.go
Outdated
|
|
||
| // Validate validates the given reader against the schema of the wrapped media type. | ||
| func (v Validator) Validate(src io.Reader) error { | ||
| func (v Validator) Validate(src io.Reader, verbose bool, out *log.Logger) error { |
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 there way we can do this without just piling on new arguments? Usually, one can tell they are on the path to spaghetti code when orthogonal arguments show up throughout the call chain.
Validate should only validate.
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.
@stevvooe
What blocked me is that validate functions (ValidateLayout/Validate/(Validator).Validate) (maybe) MUST return new variable of digest list, for these functions calculate digests internally.
If digest list can be added to validate functions when returning, I can utilize them out of validate-function. Otherwise, spaghetti code seems can't work out the problem because of these internal digests variable.
new returning variable is needed.
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 assume that you mean
func output(verbose bool, out *logger, validate functype){
// todo
}I mean a returned digests is needed from validate functype.
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 was proposing a context like object here #288 (comment) and achieve what @s-urbaniak is saying here #234 (comment) as well
|
I am proposing classical dependency injection as per https://peter.bourgon.org/go-best-practices-2016/#program-design. |
I don't see any difference here (please correct me if I'm wrong), both are used to log stuff - and I prefer logrus |
They should be different. logrus present level, hook, etc. |
|
Different as in what they actually do - which is logging (logrus has the same API as go/log) |
|
ping @s-urbaniak @stevvooe @wking @runcom |
|
ping @s-urbaniak @stevvooe @wking @runcom
I think these functions should return the necessary digest list. |
|
On Fri, Sep 09, 2016 at 04:05:15AM -0700, xiekeyang wrote:
I think showing the digests of the blobs being fetched/validated I'm waffling on whether this is logging output or program output. I |
Signed-off-by: xiekeyang <[email protected]>
To add a optional log-level, as to output the object digest. It is to close issue #222. Signed-off-by: xiekeyang <[email protected]>
|
Here I collect guys proposal, to improve the output mechanism.
@stevvooe @s-urbaniak suggested to use spaghetti code or object function. Now I'm not sure if we need to export the descriptor from validation function, so I assume unnecessarily to use it. If you think that descriptor informations is useful out of validation functions, or current output is improper, I would amend the implementation. Thanks for all of your good proposal, PTAL. |
:/ I suggested that we avoid spaghetti code. I'm suggesting that we have an object walker to which you can attach functionality. Such a pattern might look as follows: WalkImageLayout(imageLayout, func(desc Descriptor, err error) error) {
if err := validate(imageLayout.Get(desc)); err != nil {
log.Verbose("error %v", desc)
return err
}
if verbose {
log.Verbose("validated %v", desc)
}
return nil
})This allows one to visit each item and do a few different things to it, while not overcoupling their implementation. |
|
@stevvooe that's exactly the pattern I'm working on |
|
Closing as this code was moved to https://github.com/opencontainers/image-tools. Please re-open if necessary. |
add a verbose option, to output the object digest.
It is for issue #222.
the usage is like,
If it make sense, I'd add the verbose to create command.
Signed-off-by: xiekeyang [email protected]