interfaces/hooks: PlugData and SlotData wrappers #3810

Closed
wants to merge 9 commits into
from

Conversation

Projects
None yet
5 participants
Contributor

stolowski commented Aug 25, 2017

Helper classes to access plug/slot attributes from implementations of interfaces - see https://forum.snapcraft.io/t/defining-the-behavior-of-dynamic-attributes-interface-hooks/673 for discussion.
They wrap plug/info with their "static" attributes as well as "dynamic" attributes coming from hooks - this is to simplify arguments of interface methods, avoid map[string]interface{} there and get better control over what gets modified and when (we could add checks and error out if SetStaticAttr is attempted after "Sanitize" step, but so far it was decided not to as this should be treated as programming error during the code review of an interface).

The branch that's actually using the new types is the #3120

codecov-io commented Aug 25, 2017

Codecov Report

Merging #3810 into master will decrease coverage by 0.01%.
The diff coverage is 76.23%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3810      +/-   ##
==========================================
- Coverage   75.73%   75.72%   -0.02%     
==========================================
  Files         409      410       +1     
  Lines       35388    35464      +76     
==========================================
+ Hits        26801    26854      +53     
- Misses       6690     6711      +21     
- Partials     1897     1899       +2
Impacted Files Coverage Δ
snap/info.go 89.04% <ø> (ø) ⬆️
overlord/ifacestate/implicit.go 100% <100%> (ø) ⬆️
snap/info_snap_yaml.go 94.21% <100%> (+0.16%) ⬆️
interfaces/attrs.go 62.5% <62.5%> (ø)
wrappers/binaries.go 72.72% <0%> (-6.82%) ⬇️
overlord/ifacestate/helpers.go 62.33% <0%> (ø) ⬆️
overlord/snapstate/snapstate.go 80.68% <0%> (+0.25%) ⬆️
cmd/snap/cmd_aliases.go 95% <0%> (+1.66%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a88be13...305b216. Read the comment docs.

Some early feedback, I probably don't know what you are going to do with this so some of my questions may make no sense.

interfaces/attrs.go
+}
+
+type SlotData struct {
+ slot *snap.SlotInfo
@zyga

zyga Aug 25, 2017

Contributor

Just think aloud, should this be a SlotInfo or is a SlotRef sufficient?

@stolowski

stolowski Aug 25, 2017

Contributor

No, it wouldn't bu sufficient, I need access to slot's and plug's attributes.

interfaces/attrs.go
+}
+
+type Attributes interface {
+ SetStaticAttr(key string, value interface{})
@zyga

zyga Aug 25, 2017

Contributor

Should this be allowed to fail?

@stolowski

stolowski Aug 25, 2017

Contributor

That's a good question. I need to think about it. Would make sense to fail if we wanted to prohibit setting these attributes after Sanitize* step (see the descripton of this PR).

interfaces/attrs.go
+}
+
+func (attrs *PlugData) Ref() PlugRef {
+ return PlugRef{Snap: attrs.plug.Snap.Name(), Name: attrs.plug.Name}
@zyga

zyga Aug 25, 2017

Contributor

That's just attrs.plug.Ref()

@stolowski

stolowski Aug 25, 2017

Contributor

No.. For some reason we have Ref() on Plug and Slot, but not on PlugInfo/SlotInfo. Perhaps we could have that on both for convienience, in which case this can be simplified indeed?

@zyga

zyga Aug 25, 2017

Contributor

Yes, please move them layer below.

interfaces/attrs.go
+
+func (attrs *PlugData) SetAttr(key string, value interface{}) error {
+ if attrs.dynamicAttrs == nil {
+ return fmt.Errorf("dynamic attributes not initialized")
@zyga

zyga Aug 25, 2017

Contributor

Why not just initialize this?

@stolowski

stolowski Aug 25, 2017

Contributor

We want it to fail if you attempt to set dynamic attribute before hooks are even run. This will be initialized after hooks are executed, so any AfterPreparePlug|Slot methods of interfaces will be able to call it without error.

@zyga

zyga Aug 25, 2017

Contributor

In that case it feels more like a panic

@pedronis

pedronis Aug 25, 2017

Contributor

my understanding is that this can be called also in the equivalent to Sanitize for setting defaults that is ok to override later

@pedronis

pedronis Aug 28, 2017

Contributor

to be clear I think to implement that

            plugs:     make(map[string]map[string]*Plug),
            slots:     make(map[string]map[string]*Slot)

in repo needs to use *Data instead, then we would clone them before using them to make connections and then keep track of the final connection attributes with some object keeping those cloned/finalized *Data sides

interfaces/attrs.go
+}
+
+func (attrs *SlotData) Ref() SlotRef {
+ return SlotRef{Snap: attrs.slot.Snap.Name(), Name: attrs.slot.Name}
@zyga

zyga Aug 25, 2017

Contributor

This is just attrs.slot.Ref()

@stolowski

stolowski Aug 25, 2017

Contributor

See my answer re plug.Ref above.

@zyga

zyga Aug 25, 2017

Contributor

Ack

interfaces/attrs.go
+ }
+}
+
+func (attrs *PlugData) Interface() string {
@mvo5

mvo5 Aug 28, 2017

Collaborator

I am slightly unhappy about the boilerplate duplication between PlugData and SlotData, a lot of the helpers are identical except for attrs.{plug,slot}. I think by re-organizing the structs a bit we could avoid some of this duplication. Here is an outline of what I have in mind: http://paste.ubuntu.com/25416348/ - it avoids duplication but adds a bit of complexity (via the common base type but without losing type safety) so we need think about the trade-off here, i.e. it might not be worth it. With that refactor: Interface,Name,Snap,Apps,StaticAttr,SetStaticAttr,StaticAttrs,Attr,Attrs,SetAttr would all be common code. Only Ref and SecurityTags would be type specific.

@mvo5

mvo5 Aug 28, 2017

Collaborator

pushed to https://github.com/mvo5/snappy/tree/hook-attrs-refactor for easier cherry-pick (if we want to go down this path).

stolowski and others added some commits Aug 29, 2017

- Interface: iface,
- Attrs: attrs,
- Label: label,
+ PlugSlotData{
@pedronis

pedronis Sep 5, 2017

Contributor

this kind of change looks a bit odd tbh, given that is all exported and not some internal detail

+}
+
+type plugSlotData struct {
+ data *snap.PlugSlotData
@pedronis

pedronis Sep 5, 2017

Contributor

sharing data with the original like this is probably not useful, misleading. As I wrote in one comment the point is more that the repo should be moved to be *Data based.

@pedronis

pedronis Sep 5, 2017

Contributor

we should treat the *Info stuff as immutable, and deal with repos/interfaces needing to do mutations by using copies, the new *Data stuff

Contributor

stolowski commented Sep 18, 2017

Closing for now.

@stolowski stolowski closed this Sep 18, 2017

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