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

add OCIError to differentiate 'MUST/SHOULD' and add reference support #354

Merged
merged 4 commits into from
Jul 28, 2017

Conversation

liangchenye
Copy link
Member

this is an implementation of #353 .

PTAL
@wking @Mashimiao @mrunalp

@@ -642,6 +644,12 @@ func validate(context *cli.Context) error {
err := v.test(spec)
t.Ok(err == nil, v.description)
if err != nil {
if logLevel >= logrus.ErrorLevel {
// Skip 'SHOULD', 'MAY' ...
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't like overloading logrus.ErrorLevel to control this, since “SHOULD violations are fatal” is not the same as “I want to see debug logging”. Can we add a setting to the Validator structure to control this for config validation, and a command-line parameter to runtimetest to control this for runtime validation?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, overloading logrus is a little bit tricky.
I'll use another flag like 'rfc-level'.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe compliance-level would be better than rfc-level? There are many RFCs, and what we're interested in here is how well the tested-thing complies with the specification.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll update with all your good suggestions tomorrow. It is a little bit late here.

Err error
}

const ReferencePrefix = "https://github.com/opencontainers/runtime-spec/blob/master/"
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of floating this with master, we should be using the ociVersion of the config we're checking against. This is another reason that we should only be supporting tagged spec releases.

Copy link
Member Author

Choose a reason for hiding this comment

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

The current version is: '-rc5-dev' and we don't have a matched release.
We can change it after v.1.0.0 release, for example: https://github.com/opencontainers/runtime-spec/blob/v1.0.0/config-linux.md

Copy link
Contributor

Choose a reason for hiding this comment

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

The current version is: '-rc5-dev'…

The current runtime-spec version supported by runtime-tools' master is -rc1-dev. If we make the adjustment I'm asking for in the in-flight #349, we can target -rc5. I see no purpose to targeting -rc5-dev.

@wking
Copy link
Contributor

wking commented Mar 30, 2017 via email

@liangchenye
Copy link
Member Author

All the 'MUST-level' errors need to be filled. We can add all ErrorCode. It also helps to track #66.

@liangchenye
Copy link
Member Author

Updated:
add a 'compliance-level' option to runtimetest.
add man page and complete bash

The tagged release and other 'MUST' error will be added in the following commits.

PTAL @wking @mrunalp @hqhq @Mashimiao

@@ -0,0 +1,69 @@
package validate
Copy link
Contributor

Choose a reason for hiding this comment

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

How would you feel about pulling this out into its own package? I think image-spec and image-tools would also benefit from this approach to handling compliance levels?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think image-tool could use the same OCIError struct. But OCIErrorCode can not be shared between runtime-tool and image-tool. I think we can keep it here.

Copy link
Contributor

Choose a reason for hiding this comment

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

But OCIErrorCode can not be shared between runtime-tool and image-tool. I think we can keep it here.

Yeah. A stand-alone module with all the tooling and a public code-> string map, and then the validating consumer populates that map (and spec URL) for whatever it's testing.

Copy link
Member Author

Choose a reason for hiding this comment

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

The runtime-tool and image-tool are separated, where should we have such a 'stand-alone module', "opencontainers/certification"?

Copy link
Contributor

Choose a reason for hiding this comment

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

The runtime-tool and image-tool are separated, where should we have such a 'stand-alone module', ...

I was thinking a separate sub-package in this repo. Or maybe in runtime-spec, since both image repos currently have some runtime-spec connections. It seems too tiny for its own repo, and opencontainers/certification seems more focused on policy than implementation.

Err error
}

//FIXME: change to tagged spec releases
Copy link
Contributor

Choose a reason for hiding this comment

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

In order to support this future change, we probably want to include a SpecVersion field in the OCIError structure.

Copy link
Member Author

Choose a reason for hiding this comment

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

How about add a field (not in this PR) like this :
SpecVersions []string

So each OCI Error will be associate with one or more spec versions.
In runtimetest, we can add another option:
spec-version.
So if an OCI Error does not have the wanted spec-version, we can ignore it.

Copy link
Contributor

Choose a reason for hiding this comment

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

So each OCI Error will be associate with one or more spec versions.

I think it's better to only test against the spec for the target version. But if we're passing around that target version so we can decide what conditions to test, there's probably no need to stash it on Error. I'll withdraw my suggestion, and we can leave the struct fields alone.

Copy link
Contributor

Choose a reason for hiding this comment

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

With #349 landed we can fix this FIXME.

)

// OCIError represents an error with compliance level and OCI reference
type OCIError struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

This type is already OCI-namespaced via the package path (github.com/opencontainers/runtime-tools/validate). I think we can just go with Error as the struct name.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK

case "SHOULD":
return ComplianceShould
case "MUST":
return ComplianceMust
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't seem quite right. RFC 2119 has the following levels:

  • MUST-level (MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT).
  • SHOULD-level (SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED).
  • MAY-level (MAY, OPTIONAL).

You've listed yours in the inverse order from the RFC (and left off NOT RECOMMENDED?), and that means that your ComplianceMustNot is less than your ComplianceMust, even though both should be in the MUST-level. I recommend either:

a. Reorder your constants to put ComplianceShould at the bottom of the SHOULD-level constants and ComplianceMust at the bottom of the MUST-level constants.
b. Add a function that maps the constants to their level (e.g. ComplianceLevel(ComplianceShallNot) → ComplianceMust) and use that when deciding whether errors are fatal.
c. Adjust this case here to select whatever the lowest constant is for that level (e.g. "MUST" → ComplianceShall).

Copy link
Member Author

Choose a reason for hiding this comment

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

updated with solution C.

@Mashimiao
Copy link

Mashimiao commented Apr 11, 2017

LGTM

Approved with PullApprove

@Mashimiao Mashimiao modified the milestone: 0.6 Apr 11, 2017
@liangchenye
Copy link
Member Author

@hqhq @mrunalp PTAL

__oci-runtime-tool_complete_compliance_level() {
COMPREPLY=( $( compgen -W "
must
should
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing may (which is documented here). Although I'm not sure what MAY-level validation looks like, and would be fine dropping it from --compliance-level.

Copy link
Member Author

Choose a reason for hiding this comment

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

Lost 'may' in previous PR. We have 'MAY' in spec. In this case, we 'may' print 'MAY' information when platform.os is linux but the linux item is not set.

Copy link
Contributor

Choose a reason for hiding this comment

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

In this case, we 'may' print 'MAY' information when platform.os is linux but the linux item is not set.

So would this be all unset OPTIONAL child properties? Or more case-by case at the runtime-tools maintainers descretion? Either was, a fatal level seems odd. If something deserves occasional fatal warnings, it should probably be SHOULD in the spec.

Err error
}

//FIXME: change to tagged spec releases
Copy link
Contributor

Choose a reason for hiding this comment

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

With #349 landed we can fix this FIXME.


for fs, fstype := range defaultFS {
if !(mountsMap[fs] == fstype) {
return ociErr.NewError(ociErr.DefaultFilesystems, fmt.Sprintf("%v must exist and expected type is %v", fs, fstype))
Copy link
Contributor

Choose a reason for hiding this comment

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

“must” → “SHOULD”.

var validationErrors error
for _, v := range defaultValidations {
err := v.test(spec)
t.Ok(err == nil, v.description)
if err != nil {
if e, ok := err.(*ociErr.Error); ok && e.Level < complianceLevel {
continue
Copy link
Contributor

Choose a reason for hiding this comment

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

We may want to print these as warnings even if they are non-fatal. With TAP, I'd recommend using diagnostics. I'm not sure what the best approach is with Go's testing framework, but we should probably figure that out ;).

Copy link
Member Author

Choose a reason for hiding this comment

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

I opened #362 to keep track of this.

case "REQUIRED":
return ComplianceMust
default:
return ComplianceMust
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the default should be to raise an “unrecognized level” error. Silently defaulting to MUST seems confusing.

Copy link
Member Author

Choose a reason for hiding this comment

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

you are right. I should raise error here.

// NewError creates an Error by ErrorCode and message
func NewError(code ErrorCode, msg string) error {
err := ociErrors[code]
err.Err = errors.New(msg)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this making a new Error? It looks like it's attaching a new error to a pre-existing Error (possibly clobbering a previous error). Or maybe we will only ever report one error for a given ErrorCode and we want that clobbering? Or maybe I'm misreading this and we are creating a new Error ;).

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm creating a new Error :) So the OCIError could be used as a normal Error.

@liangchenye
Copy link
Member Author

Updated by

  1. add 'may' in completion file
  2. reference with 'released' version
  3. return error when ParseLevel with unrecognized string

PTAL @wking @Mashimiao @mrunalp @hqhq

Signed-off-by: liangchenye <liangchenye@huawei.com>
Signed-off-by: liangchenye <liangchenye@huawei.com>
Signed-off-by: liangchenye <liangchenye@huawei.com>
@liangchenye liangchenye force-pushed the master branch 3 times, most recently from 63a13b3 to ccf57b5 Compare July 6, 2017 07:54
Signed-off-by: liangchenye <liangchenye@huawei.com>
@liangchenye
Copy link
Member Author

rebased and fixed the glint error. PTAL @Mashimiao @hqhq @mrunalp

@Mashimiao
Copy link

Mashimiao commented Jul 7, 2017

LGTM

Approved with PullApprove

@liangchenye
Copy link
Member Author

@hqhq @mrunalp PTAL

@liangchenye
Copy link
Member Author

@q384566678 PTAL

@@ -30,6 +32,13 @@ const PrGetNoNewPrivs = 39
const specConfig = "config.json"

var (
defaultFS = map[string]string{
"/proc": "proc",

Choose a reason for hiding this comment

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

proc -> procfs

Choose a reason for hiding this comment

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

proc here is right, there is no procfs such type in Linux

Choose a reason for hiding this comment

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

Choose a reason for hiding this comment

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

we call it procfs but the real type in Linux is proc. I will submit a PR to fix it in runtime-spec

Choose a reason for hiding this comment

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

fine.

@zhouhao3
Copy link

zhouhao3 commented Jul 28, 2017

LGTM

Approved with PullApprove

1 similar comment
@Mashimiao
Copy link

Mashimiao commented Jul 28, 2017

LGTM

Approved with PullApprove

@Mashimiao Mashimiao merged commit 3a21ae6 into opencontainers:master Jul 28, 2017
wking added a commit to wking/ocitools-v2 that referenced this pull request Jul 28, 2017
As discussed in [1].  This makes it easier for other projects
(e.g. image-tools) to use the same tooling if they want.  Some
components of the old validate/error.go were runtime-spec-specific
(e.g. the reference template and ociErrors), so they've stayed in the
validate package.

I've also expanded NewError to take an explicit version (as requested
in [2]).  That allows us to link to the proper spec even if we're
capable of validating several spec versions (e.g. 1.0 and 1.1
configurations or runtimes).

[1]: opencontainers#354 (comment)
[2]: opencontainers#354 (comment)

Signed-off-by: W. Trevor King <wking@tremily.us>
wking added a commit to wking/ocitools-v2 that referenced this pull request Jul 28, 2017
As discussed in [1].  This makes it easier for other projects
(e.g. image-tools) to use the same tooling if they want.  Some
components of the old validate/error.go were runtime-spec-specific
(e.g. the reference template and ociErrors), so they've stayed in the
validate package.

I've also expanded NewError to take an explicit version (as requested
in [2]).  That allows us to link to the proper spec even if we're
capable of validating several spec versions (e.g. 1.0 and 1.1
configurations or runtimes).

[1]: opencontainers#354 (comment)
[2]: opencontainers#354 (comment)

Signed-off-by: W. Trevor King <wking@tremily.us>
@Mashimiao Mashimiao removed this from the v0.6.0 milestone Sep 15, 2017
wking added a commit to wking/ocitools-v2 that referenced this pull request Oct 2, 2017
The man-page entry and Bash completions for this option were added in
4029999 (oci error: add error level and reference, 2017-03-31, opencontainers#354),
but the option was left unimplemented.  The implementation in this
commit is very similar to the existing runtimetest implementation from
4029999, except we warn instead of silently skipping non-fatal spec
violations.

The warning (vs. error) on invalid level arguments follows the
runtimetest implementation from 6316a4e (use released version as
reference; improve Parse error, 2017-04-12, opencontainers#354).  I'd personally
prefer hard errors on invalid level arguments, but didn't want to
break runtime-tools consistency over that.

Signed-off-by: W. Trevor King <wking@tremily.us>
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.

4 participants