Caps type attrs #205

Merged
merged 13 commits into from Dec 3, 2015

Conversation

Projects
None yet
4 participants
Contributor

zyga commented Dec 2, 2015

This branch adds simple attribute validation to capability types. Each type now contains the list of attributes that must (and only those) be present in a capability.

zyga added some commits Dec 1, 2015

Add caps.Type.SupportedAttrs
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Add support for simple capability attribute validation
This patch ensures, via caps.Type.Validate(), that capabilities have
only attributes that are expected. The actual value of attributes is
not checked, just their presence.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Use caps.testType instead of FileType
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
caps/types.go
- if c.Attrs != nil && len(c.Attrs) != 0 {
- return fmt.Errorf("attributes must be empty for now")
+ // Check that all supported attributes are present
+ for _, attr := range t.SupportedAttrs {
@mvo5

mvo5 Dec 2, 2015

Collaborator

Hm, if I read this correctly it will fail if a "SupportedAttr" is missing? If thats the case, maybe it should be "t.RequiredAttrs" instead as the name? To make more clear that this is a mandatory attribute?

@zyga

zyga Dec 2, 2015

Contributor

I was actually looking for "mandatory/required + only (no other allowed).

I'll rename this to RequiredAttrs for now

zyga added some commits Dec 2, 2015

Trivial golint suggestion
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Rename caps.Type.SupportedAttrs to RequiredAttrs
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Tweak initializer for known capability types
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
caps/types.go
@@ -31,6 +31,9 @@ type Type struct {
// Name is a key that identifies the capability type. It must be unique
// within the whole OS. The name forms a part of the stable system API.
Name string
+ // RequiredAttrs contains names of attributes that are understood by
@mvo5

mvo5 Dec 2, 2015

Collaborator

In nitpick mode now (sorry for that!). Maybe instead of "that are understood by" "that are required by" ?

@zyga

zyga Dec 2, 2015

Contributor

Ack, corrected.

caps/types.go
- // show that this code is actually being used.
- if c.Attrs != nil && len(c.Attrs) != 0 {
- return fmt.Errorf("attributes must be empty for now")
+ // Check that all supported attributes are present
@mvo5

mvo5 Dec 2, 2015

Collaborator

(nitpick) supported -> required (?)

@zyga

zyga Dec 2, 2015

Contributor

Fixed

Tweak wording on caps.Type.RequiredAttrs
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
caps/types.go
+ // Look for any unexpected attributes
+ if len(t.RequiredAttrs) != len(c.Attrs) {
+ for attr := range c.Attrs {
+ supported := false
@mvo5

mvo5 Dec 2, 2015

Collaborator

(nitpick, probably over the top this time). Its a bit unfortunate that there is no "Contains()" outside of the testutil package :) I think this would be easier to read by:

for attr := range c.Attrs {
            if !Contains(t.RequiredAttrs, attr)  {
                return fmt.Errorf("capability contains unexpected attribute %q", attr)
            }

But not for this branch :)

Tweak comment in caps.Type.Validate()
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Collaborator

mvo5 commented Dec 2, 2015

Thanks, looks good to me.

caps/types.go
+ }
+ }
+ if !supported {
+ return fmt.Errorf("capability contains unexpected attribute %q", attr)
@chipaca

chipaca Dec 2, 2015

Member

I think you should wait until the end of the loop and report all unexpected attribtues, not just the first one at random.

@chipaca

chipaca Dec 2, 2015

Member

you've got to be <---------- this ----------> nitpicky to follow this suggestion

Member

chipaca commented Dec 2, 2015

lgtm

caps/types.go
+ // Check that all required attributes are present
+ for _, attr := range t.RequiredAttrs {
+ if _, ok := c.Attrs[attr]; !ok {
+ return fmt.Errorf("capability lacks required attribute %q", attr)
@niemeyer

niemeyer Dec 2, 2015

Contributor
("capabilities of type %q must provide a %q attribute", t, attr)
@zyga

zyga Dec 2, 2015

Contributor

Fixed

caps/types.go
+ return fmt.Errorf("capability lacks required attribute %q", attr)
+ }
+ }
+ // Look for any unexpected attributes
@niemeyer

niemeyer Dec 2, 2015

Contributor

This will break forwards compatibility in a really bad way. Think in terms of code: imagine you have a Python type that millions of people are using, and then when you decide to add a new method on that type, you break every single existing application out there.

@zyga

zyga Dec 2, 2015

Contributor

Can you explain this more please? I've made it precisely so that we have forward compatibility. Otherwise anyone can ship a product with a "foo" type that has a custom, unexpected "bar" attribute that we want to use but now cannot because shipping products and snaps have already used it.

Down the line I have an idea for type versions so that we can release, say, "bool-file" v2 with more attributes and applications that want to see that can use the new attributes (perhaps with new usage semantics as well, that are not strictly encoded in attributes but this is unrelated).

When we ship a type we ship it with fixed set of attributes. Each time we want to change what they are, what they mean, we bump the version and ship another capability (version) that represents the same resource. This gives us future-compatibility by letting us evolve types over time.

Obviously you had something else on your mind so please explain what you mean again and I'll adjust the code.

caps/types_test.go
+ Name: "name",
+ Label: "label",
+ Type: t,
+ Attrs: map[string]string{},
@niemeyer

niemeyer Dec 2, 2015

Contributor

Why do we need an empty map here? The logic should handle nil maps okay, right?

There should also be another test with a non-empty map but non-matching attributes, and also another positive test which has both matching and non-matching attributes but the required attributes satisfied.

@zyga

zyga Dec 2, 2015

Contributor

No need, removed now.

The second part is fixed with the exception that the last test you've mentioned is not implemented (since I didn't change Validate() yet as I need to wait for your explanation).

zyga added some commits Dec 2, 2015

Tweak error message on caps.Type.Validate()
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Remove needless initializer
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Add another test for capability/type attribute validation
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Contributor

niemeyer commented Dec 3, 2015

Just for record keeping, this still has some issues to address.

Don't check for unexpected capability attributes
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Contributor

zyga commented Dec 3, 2015

I think this is fixed now

Member

chipaca commented Dec 3, 2015

@niemeyer AFAICT everything was addressed; landing this now (if we missed anything, there's plenty of branches in the pipeline where we can address whatever it was).

chipaca added a commit that referenced this pull request Dec 3, 2015

@chipaca chipaca merged commit 7a833ac into snapcore:master Dec 3, 2015

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
coverage/coveralls First build on master at 66.537%
Details

@zyga zyga deleted the zyga:caps-type-attrs branch Dec 3, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment