many: add the interface command #3399

Merged
merged 78 commits into from Jul 26, 2017

Conversation

Projects
None yet
5 participants
Contributor

zyga commented May 24, 2017

This branch adds a new command that displays interface information. By default it shows all interfaces
that have at least one connection. When invoked with an interface name it displays details of that
particular interface, such as the plugs and slots, labels and attributes (if requested).

zyga added some commits May 23, 2017

interfaces: rename interfaceMetaData to MetaDataOf
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add InterfaceInfo that describes an interface and its ins…
…tances

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: omit empty interface name and label in plug/slot marshaling
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: refactor tests to allow tests to reuse plug/slot defs
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add JSON marshaling helper for InterfaceInfo
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add Repository.InterfaceInfos
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: tweak description of the network interface
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
daemon: add /v2/interface endpoint returning interface infos
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: add InterfaceInfo and InterfaceInfos
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: add Summary and DocumentationURL to InterfaceMetaData
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: add "snap interface" command
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

codecov-io commented May 24, 2017

Codecov Report

Merging #3399 into master will increase coverage by 0.13%.
The diff coverage is 66.02%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master   #3399      +/-   ##
=========================================
+ Coverage   75.06%   75.2%   +0.13%     
=========================================
  Files         383     384       +1     
  Lines       33238   33538     +300     
=========================================
+ Hits        24951   25222     +271     
- Misses       6477    6494      +17     
- Partials     1810    1822      +12
Impacted Files Coverage Δ
interfaces/builtin/network.go 100% <ø> (ø) ⬆️
interfaces/builtin/account_control.go 100% <ø> (ø) ⬆️
interfaces/builtin/password_manager_service.go 100% <ø> (ø) ⬆️
interfaces/builtin/alsa.go 100% <ø> (ø) ⬆️
interfaces/builtin/hidraw.go 66.97% <0%> (ø) ⬆️
interfaces/builtin/modem_manager.go 53.19% <0%> (ø) ⬆️
interfaces/builtin/maliit.go 57.89% <0%> (ø) ⬆️
interfaces/builtin/serial_port.go 67.27% <0%> (ø) ⬆️
interfaces/builtin/iio.go 70.31% <0%> (ø) ⬆️
interfaces/builtin/online_accounts_service.go 80% <0%> (ø) ⬆️
... and 59 more

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 825ca27...fbea4c4. Read the comment docs.

client/interfaces.go
+type InterfaceInfo struct {
+ MetaData InterfaceMetaData `json:"meta-data"`
+ Plugs []Plug `json:"plugs,omitempty"`
+ Slots []Slot `json:"slots,omitempty"`
@niemeyer

niemeyer May 29, 2017

Contributor

Can we merge InterfaceInfo and InterfaceMetaData into a single type named Interface?

Note that the current Interfaces type holds Plugs and Slots, exactly the same as above.

@zyga

zyga May 30, 2017

Contributor

Sure, on it

client/interfaces.go
// InterfaceMetaData contains meta-data about a given interface type.
type InterfaceMetaData struct {
- Description string `json:"description,omitempty"`
+ Summary string `json:"summary,omitempty"`
@niemeyer

niemeyer May 29, 2017

Contributor

We're also missing Name here.

@zyga

zyga Jun 5, 2017

Contributor

Done

client/interfaces.go
- Description string `json:"description,omitempty"`
+ Summary string `json:"summary,omitempty"`
+ Description string `json:"description,omitempty"`
+ DocumentationURL string `json:"documentation-url,omitempty"`
@niemeyer

niemeyer May 29, 2017

Contributor

DocURL (doc-url)? I'm generally not the one suggesting such shortenings, but that's a very common prefix, 10 less letters, and no reading loss.

@zyga

zyga Jun 5, 2017

Contributor

Done

@zyga

zyga Jun 5, 2017

Contributor

Done

client/interfaces.go
@@ -82,6 +91,12 @@ func (client *Client) Interfaces() (interfaces Interfaces, err error) {
return
}
+// InterfaceInfos returns all interfaces, their meta-data, plugs and slots.
+func (client *Client) InterfaceInfos() (infos map[string]InterfaceInfo, err error) {
@niemeyer

niemeyer May 29, 2017

Contributor

This is sort of getting back to the prior design, except in a different endpoint. How about:

  • Interface(name string) (*Interface, error)
  • InterfaceNames() ([]string, error)

?

@zyga

zyga May 30, 2017

Contributor

+1

@zyga

zyga May 30, 2017

Contributor

On second thought. How would this work with the current implementation that just displays a list of name + summary? We'd have to make 1+N calls to do that (one to get the names, then one for each name).

How about we return some basic meta-data (summary) alongside the name from InterfaceNames()? (perhaps it should be renamed to be appropriate)

@zyga

zyga Jun 5, 2017

Contributor

I did something like this (separate methods) but still allowed the "list" method to return both name and summary.

zyga added some commits May 30, 2017

cmd/snap: allow listing unused interfaces in snap interface
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add byInterfaceName helper for sorting []Interface
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add Repository.AllInterfaces for retrieving all interfaces
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add sort helpers for []snap.{Plug,Slot}Info
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add Repository.InterfaceInfo for inspecting specific inte…
…rface

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: return interface name in InterfaceInfo
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: flatten meta-data into interface info JSON
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: refactor new interface api to list + details
Currently there is one API endpoint for everything related to all the
interfaces on the system. This patch splits it into two, list and
details.

The list interface returns just the names (though this may evolve to
names + basic meta-data) and a details endpoint that returns complete
details about a single interface.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: add Name to interface information
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add repository.UsedInterfaces
This patch adds a helper function that shows which of the interfaces in
the repository is actively used. Used interfaces are those that have a
plug or slot in the system, with the exception of implicit slots
provided by the core snap.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
daemon: add method for getting index of interfaces
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: track interface-used flag in InterfaceInfo
Interfaces are used when there are any plugs or any slots (with the
exception of the core snap which provides numerous slots that don't
count as used).

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: compute the Used flag in InterfaceInfo
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: return the Used flag in JSON encoding of InterfaceInfo
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add test for InterfaceServiceName
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: improve sort code
This patch improves sort code (some silly copy-pasted, harmless but
needleess code is now removed) and adds full test coverage. Tests are
also in a _test package and are no longer polutting the main namespace.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
daemon: add method for getting details of interface
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
daemon: remove previous interface index+details method
This patch removes the previous iteration of the (unreleased) interface
listing + detail method. This is now provided by two separate methods.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add support for meta-data to TestInterface
This allows testing various interactions with meta-data.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: add Used flag to Interface
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: change InterfaceNames to return summary and used flag as well
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: replace InterfaceNames with InterfaceIndex
The old method returned just names but that was insufficient for
implementing "snap interface" which shows name, summary and hides
unused interfaces. The new method returns all the additional data
and since it returns more than just names, a new function was in order.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: rewrite "snap interface" to use new REST APIs
This patch rewrites the "snap interface" command to use two distinct REST
methods, one to list interfaces along with the summary and another one
that returns all the details of a single interface.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
many: abbreviate DocumentationURL to DocsURL
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
tests: add spread test for "snap interface"
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces/builtin: test meta-data of alsa interface
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
+ snap interface | MATCH 'core-support\s+ special permissions for the core snap'
+ snap interface --all | MATCH 'classic-support\s+ special permissions for the classic snap'
+ snap interface core-support > out.yaml
+ diff -u out.yaml snap-interface-core-support.yaml
@mvo5

mvo5 Jun 7, 2017

Collaborator

When I was reading this I was wondering where snap-interface-core-support.yaml comes from, maybe just create it in the task.yaml itself via a here shell construct?

Thanks for pushing it forward. A few comments:

client/interfaces.go
+// Interface holds information about a given interface and its instances.
+type Interface struct {
+ Name string `json:"name,omitempty"`
+ Summary string `json:"summary,omitempty"`
Description string `json:"description,omitempty"`
@niemeyer

niemeyer Jun 9, 2017

Contributor

I suggest dropping this for the time being. Summary + DocURL should cover it.

@zyga

zyga Jul 14, 2017

Contributor

Done

client/interfaces.go
Description string `json:"description,omitempty"`
+ DocsURL string `json:"docs-url,omitempty"`
@niemeyer

niemeyer Jun 9, 2017

Contributor

DocURL, I think? "DocumentationS" sounds strange.

@zyga

zyga Jul 14, 2017

Contributor

Applied

client/interfaces.go
+ DocsURL string `json:"docs-url,omitempty"`
+ Plugs []Plug `json:"plugs,omitempty"`
+ Slots []Slot `json:"slots,omitempty"`
+ Used bool `json:"used,omitempty"`
@niemeyer

niemeyer Jun 9, 2017

Contributor

The term is too vague given the context. Does it mean existing plugs? slots? connections?

Also, it most likely means the client is receiving data it doesn't need to. Better to filter upfront I think.

@zyga

zyga Jun 9, 2017

Contributor

This is so that we can ask for snap interface --all and see anything our snapd understands, even if we don't use it.

@niemeyer

niemeyer Jun 19, 2017

Contributor

The comment above was based on that understanding.

@zyga

zyga Jul 14, 2017

Contributor

I think we can drop this with the updated API design below.

client/interfaces.go
+// InterfaceIndex returns the list of all interface names.
+//
+// The result will only have three fields populated, Name, Summary and Used.
+func (client *Client) InterfaceIndex() (ifaces []Interface, err error) {
@niemeyer

niemeyer Jun 9, 2017

Contributor
/v2/snaps
/v2/interfaces
/v2/changes
/v2/users
/v2/sections
/v2/aliases

@zyga @chipaca Something smelling strange about /v2/interface. We should try to preserve some sort of consistency in the API across the several endpoints.

Looking through it, here is a proposal:

  1. Rename the current Interfaces method to Connections (we can worry about the type later)
  2. Use Interfaces to return []*Interface; note the pointer result. Every type should be a pointer in these cases unless you have a good reason to believe return by value is the right thing to do (again, see existing cases)
  3. Introduce InterfacesOptions as {Doc, Plugs, Slots, Connected bool}, meaning whether to return documentation, plugs, slots, and whether to return only connected interfaces.
  4. We can provide "connected" via a "select" field, analogous to the one we use for snaps, and then allow specifying "select=all" so that we preserve the result as-is when "select" is not provided, preserving compatibility with existing clients (including the current Interfaces method which will now become Connections). Eventually we can obsolete that result as we'll likely kill the "interfaces" command and introduce a more polished "connections" one, per our conversations.
  5. We should also support a "names" parameter in the Interfaces method analogous to the List method ("interfaces" parameter in the HTTP request, if we want to preserve the convention established by snaps). This would allow only a subselection of interfaces to be listed.

What do you think?

@zyga

zyga Jul 17, 2017

Contributor

This makes total sense, on 2nd read, with fresh head. I'm mid-way through the implementation. Hopefully will be in a reviewable state by EOD today.

@zyga

zyga Jul 24, 2017

Contributor

Pushed (though the sprint pushed this by a week)

client/interfaces.go
+}
+
+// Interface returns all interfaces, their meta-data, plugs and slots.
+func (client *Client) Interface(name string) (iface Interface, err error) {
@niemeyer

niemeyer Jun 9, 2017

Contributor

Pointer result, /v2/interfaces/+name, doc is wrong.

@zyga

zyga Jul 24, 2017

Contributor

This function is gone now (the daemon API as well)

cmd/snap/cmd_interface.go
+ } `positional-args:"true"`
+}
+
+var shortInterfaceHelp = i18n.G("Lists interfaces in the system")
@niemeyer

niemeyer Jun 9, 2017

Contributor

"Shows snap interfaces"

@zyga

zyga Jul 14, 2017

Contributor

Applied

cmd/snap/cmd_interface.go
+
+var shortInterfaceHelp = i18n.G("Lists interfaces in the system")
+var longInterfaceHelp = i18n.G(`
+The interface command lists interfaces available in the system.
@niemeyer

niemeyer Jun 9, 2017

Contributor
The interface command shows details of snap interfaces.

If no interface name is provided, a list of interface names with at least
one connection is shown, or a list of all interfaces if --all is provided.
@zyga

zyga Jul 14, 2017

Contributor

Applied

cmd/snap/cmd_interface.go
+The interface command lists interfaces available in the system.
+
+By default a list of all used interfaces, along with a short summary, is
+displayed. Use the --all option to include unused interfaces.
@niemeyer

niemeyer Jun 9, 2017

Contributor

Per note above, instead of unused we need to say what it really means.

@zyga

zyga Jul 14, 2017

Contributor

Done

cmd/snap/cmd_interface.go
+By default a list of all used interfaces, along with a short summary, is
+displayed. Use the --all option to include unused interfaces.
+
+$ snap interfaces [--attrs] <interface>
@niemeyer

niemeyer Jun 9, 2017

Contributor

This and the paragraph below may be dropped. It's just restating the documentation of --attrs.

@zyga

zyga Jul 14, 2017

Contributor

Done

cmd/snap/cmd_interface.go
+ return err
+ }
+ if len(ifaces) == 0 {
+ return fmt.Errorf(i18n.G("no interfaces found"))
@niemeyer

niemeyer Jun 9, 2017

Contributor

Something else is wrong, right?

@zyga

zyga Jun 9, 2017

Contributor

It can happen before you pull in the core snap, no snaps, no interfaces used.

@niemeyer

niemeyer Jun 19, 2017

Contributor

Yeah, so it'd be nicer to be more clear about what's going on, instead of making the user wonder.

@niemeyer

niemeyer Jun 19, 2017

Contributor

"no interfaces currently connected" would probably be better, for example.

@zyga

zyga Jul 14, 2017

Contributor

Done

cmd/snap/cmd_interface.go
+ if iface.Summary != "" {
+ fmt.Fprintf(w, "summary:\t%s\n", iface.Summary)
+ }
+ if iface.Description != "" {
@niemeyer

niemeyer Jun 9, 2017

Contributor

Let's please drop the description for now and use the URL instead.

@zyga

zyga Jun 9, 2017

Contributor

+1

@zyga

zyga Jul 14, 2017

Contributor

Done

cmd/snap/cmd_interface.go
+ fmt.Fprintf(w, "description: |\n%s\n", formatDescr(iface.Description, termWidth))
+ }
+ if iface.DocsURL != "" {
+ fmt.Fprintf(w, "docs-url:\t%s\n", iface.DocsURL)
@niemeyer

niemeyer Jun 9, 2017

Contributor

I think this can say:

("documentation:\t%s\n", iface.DocURL)

Perhaps even dropping those \t? Not sure if they're helping much in this case.

@zyga

zyga Jun 9, 2017

Contributor

They make the yaml format nice, I think. Let me experiment.

@zyga

zyga Jul 14, 2017

Contributor

Done

cmd/snap/cmd_interface.go
+ }
+ if len(iface.Plugs) > 0 {
+ fmt.Fprintf(w, "plugs:\n")
+ for _, plug := range iface.Plugs {
@niemeyer

niemeyer Jun 9, 2017

Contributor

This might be much nicer as:

plugs:
  - mysnap:myplug
  - othesnap:otherplug
slots:
  - blah:blah
@zyga

zyga Jul 14, 2017

Contributor

This would preclude us from displaying attributes or even useful things like the label. Let me experiment to see what I can do to display both.

EDIT: OK, I think you will be happy, it's exactly as you specified but I can still show label and attributes if there are some.

Contributor

niemeyer commented Jun 19, 2017

@zyga This is ready for some love.

Member

chipaca commented Jul 10, 2017

If this needs to be reworked, should this PR be closed meanwhile?

@chipaca chipaca added the Decaying label Jul 10, 2017

Contributor

zyga commented Jul 10, 2017

Yes, I'll close it and re-open once everything is addressed.

@zyga zyga closed this Jul 10, 2017

zyga added some commits Jul 14, 2017

Merge branch 'master' of github.com:snapcore/snapd into feature/inter…
…face-command

Resolved few small conflicts around function renames that happened in
two branches separately but with different resulting names.
cmd/snap: reword error message
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
many: drop description field from interface APIs
The description is better suited for a longer page (e.g. at the forum)
and the curious user will be able to find richer text, ask questions
and interact with others. This is much better than just a dry paragrap
of description kept in snapd tree.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: rename "docs-url" to just "documentation"
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: tweak ouptut of snap interface network
The output is still valid YAML but now is more compact, showing each plug
and slot with just one line each, in most cases. When labels are present
or when attributes need to be displayed, the output morphs into a list
of objects.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: tweak help for snap interface
The help now describes what the command does (shows used interfaces) and
has more terse help for available options, along with more accurate
descriptions.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client,cmd/snap: rename Interfaces to Connections
The rename gives us a way to use Interfaces as an API method for the
upcoming refactoring of the "interface" command. The types and
on-the-wire protocol remain unchanged.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Contributor

niemeyer commented Jul 17, 2017

@zyga I'm reopening this and pulling it into the review sprint, as you seemed interested in focusing on this next.

@niemeyer niemeyer reopened this Jul 17, 2017

zyga added some commits Jul 17, 2017

client: add InterfaceOptions for selecting and adjusting search results
This structure will allow clients to select the desired subset of data
to be returned.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client,cmd,interfaces: it's *docURL* not *docsURL*
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: add new Interfaces function for querying the set of interfaces
The new function uses the same old endpoint /v2/interfaces but now uses
query options to choose the desired behavior.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: add Repository.QueryInterfaces
This patch adds a new way to query interfaces present in the repository.
The mechanism is more flexible than prior attempts and in fact replaces
them in most cases. Subsequent patches will remove some unused code or
code that can be made unused through trivial calls to QueryInterfaces.

The input is a list of names and a set of options. The names decide which
interfaces are returned. As a special case, an empty list of names will
search all of the available interfaces. The options decide what data
is returned, such as documentation or plug and slot details. One of the
options also changes the scope of the search to just those interfaces
that have at least one connection.

The return value is a list of sorted InterfaceInfo objects with various
details filled in, as requested.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: move Names to InterfaceOptions and rename to InterfaceQueryOp…
…tions

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: drop unused interface code
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: discard Repository.Used (unused)
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: discard Repository.InterfaceInfo (unused)
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

@zyga zyga removed the Decaying label Jul 24, 2017

Contributor

zyga commented Jul 24, 2017

I think this is now ready for a 2nd review.

zyga added some commits Jul 17, 2017

daemon: multiplex legacy and modern /v2/interfaces
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: move snap interface and its tab completion to new APIs
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
daemon: discard the /v2/interface endpoint and adapt tests
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: discard Repository.InterfaceInfos (unused)
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: discard Repository.AllInterfaces (unused)
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: shorter tab completion code
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: vary error message depending on options
When 'interfaces' option '--all' is used and we don't see any interfaces
it is because there are none, not because there are no connected
interfaces. Use the right message.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

Extra +1

tests: update data after output change
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

I have tried to provide concrete suggestions for how this would LGTM.. if these sound good to you, feel free to move on. Otherwise, let's please talk and agree on something by tomorrow the latest.

client/interfaces.go
-// Interfaces returns all plugs, slots and their connections.
-func (client *Client) Interfaces() (interfaces Interfaces, err error) {
+// Connections returns all plugs, slots and their connections.
+func (client *Client) Connections() (interfaces Interfaces, err error) {
@niemeyer

niemeyer Jul 25, 2017

Contributor

Let's please take out the return value names, and go ahead and rename Interfaces (the type) to Connections as well. This will read much better I think.

@zyga

zyga Jul 26, 2017

Contributor

Done

client/interfaces.go
_, err = client.doSync("GET", "/v2/interfaces", nil, nil, nil, &interfaces)
return
}
+// InterfaceQueryOptions represents opt-in elements include in responses.
+type InterfaceQueryOptions struct {
@niemeyer

niemeyer Jul 25, 2017

Contributor

FindOptions, ListOptions, SnapCtlOptions... perhaps just InterfaceOptions?

@zyga

zyga Jul 26, 2017

Contributor

Done

client/interfaces.go
+// InterfaceQueryOptions represents opt-in elements include in responses.
+type InterfaceQueryOptions struct {
+ Names []string
+ Doc, Plugs, Slots, Connected bool
@niemeyer

niemeyer Jul 25, 2017

Contributor

For such a long sequence, breaking it down into independent lines will make the code read better. Repeating the bool is less of a problem than the awkwardness of how this looks now.

@zyga

zyga Jul 26, 2017

Contributor

Done

client/interfaces.go
+ }
+ if opts != nil {
+ if opts.Doc {
+ query.Set("doc", "yes") // Return documentation of each selected interface.
@niemeyer

niemeyer Jul 25, 2017

Contributor

We use "true" in our booleans in other cases, I believe.

@zyga

zyga Jul 26, 2017

Contributor

Done

+ if err != nil {
+ return err
+ }
+ if len(ifaces) == 0 {
@niemeyer

niemeyer Jul 25, 2017

Contributor

Shouldn't that be returned by the server? What happens if there are two names, and one doesn't exist? It sounds like an error.

@zyga

zyga Jul 26, 2017

Contributor

I was looking at snap list which has similar client-side behavior. We could change the response format so that unknown interfaces can be reported but if we do so we should probably use the same approach for other listings.

cmd/snap/cmd_interface.go
+ fmt.Fprintf(w, "\n")
+ }
+ if plug.Label != "" {
+ fmt.Fprintf(w, " label:\t%s\n", plug.Label)
@niemeyer

niemeyer Jul 25, 2017

Contributor

I suspect the output will look quite displeasing and repetitive once we have tons of interfaces with labels.

Imagine:

plugs:
    - foo:bar:
        label: Foo Bar
    - foo:baz:
        label: Foo Baz
    - foo:buz:
        label: Foo Buz

I suggest something like this instead:

    - foo:bar (Foo Bar)
    - baz:buz (Baz Buz)
    - bom:bam (Bom Bam)
@zyga

zyga Jul 25, 2017

Contributor

Oh, even better. Thanks!

I think we can still stick key-value attributes below (for when we actually have any).

@zyga

zyga Jul 26, 2017

Contributor

Done

@zyga

zyga Jul 26, 2017

Contributor

I also tweaked the attributes so that the word attributes is not shown, have a look. I like it a lot.

cmd/snap/cmd_interface.go
+}
+
+func (x *cmdInterface) showAttrs(w io.Writer, attrs map[string]interface{}, indent string) {
+ if len(attrs) == 0 || !x.ShowAttrs {
@niemeyer

niemeyer Jul 25, 2017

Contributor

It's less confusing and less error prone to have the !x.ShowAttrs happening at the call site instead: to not show attrs, don't call show attrs. The len(attrs) == 0 can stay here, though, as this is just the zero case of the function.

@zyga

zyga Jul 26, 2017

Contributor

Done

interfaces/repo.go
@@ -80,6 +80,112 @@ func (r *Repository) AddInterface(i Interface) error {
return nil
}
+// QueryOptions describes options for QueryInterfaces.
@niemeyer

niemeyer Jul 25, 2017

Contributor

The terminology in the repository is getting a bit wild.. a few hints:

  • We have tons of "queries" in the repository already. Why is that different?
  • What is the difference between Info and MetaData? Note we just fixed that in the client.

I think we should change some of the existing API to also talk about "connections", but we don't have to do that now so we can both focus on more interesting problems. That said, I'll try to provide some ideas below for how to not make the API too wild for now either.

@zyga

zyga Jul 26, 2017

Contributor

I agree about connections, not just the new API end-point and new snap subcommand but also as a general term.

I think I applied all the suggestions below. Let me know if I missed anything.

interfaces/repo.go
+// Plugs: return information about plugs.
+// Slots: return information about slots.
+// Connected: only consider interfaces with at least one connection.
+type QueryOptions struct {
@niemeyer

niemeyer Jul 25, 2017

Contributor

One solution might be to organize that new functionality in terms of "information about interfaces", which is something we don't have yet. For that, we can call this type "InfoOptions".

@zyga

zyga Jul 26, 2017

Contributor

Done

interfaces/repo.go
+// Connected: only consider interfaces with at least one connection.
+type QueryOptions struct {
+ Names []string
+ Doc, Plugs, Slots, Connected bool
@niemeyer

niemeyer Jul 25, 2017

Contributor

Same as in the client, let's please split it down into independent lines.

@zyga

zyga Jul 26, 2017

Contributor

Done

interfaces/repo.go
+ Doc, Plugs, Slots, Connected bool
+}
+
+func (r *Repository) queryInterface(iface Interface, opts *QueryOptions) *InterfaceInfo {
@niemeyer

niemeyer Jul 25, 2017

Contributor

interfaceInfo is a better name for this method.

@zyga

zyga Jul 26, 2017

Contributor

Done

interfaces/repo.go
+
+func (r *Repository) queryInterface(iface Interface, opts *QueryOptions) *InterfaceInfo {
+ // NOTE: QueryOptions.Connected is handled by QueryInterfaces
+ md := MetaDataOf(iface)
@niemeyer

niemeyer Jul 25, 2017

Contributor

Same as for the client, we need to either unify metadata and info, or give MetaData a better name. As a way to move forward and not have to refactor too much right away, I suggest calling MetaData as StaticInfo, which gives a more clear delta between the place of each of these in our world: StaticInfo is the static details provided at interface declaration time, and which we do have in Info as well.

@zyga

zyga Jul 26, 2017

Contributor

I like StaticInfo, it was conveying the "bag of stuff baked into the binary" idea I had before better than the generic meta-data.

@zyga

zyga Jul 26, 2017

Contributor

I replaced MetaData with StaticInfo everywhere now.

interfaces/repo.go
+ // NOTE: QueryOptions.Connected is handled by QueryInterfaces
+ md := MetaDataOf(iface)
+ ifaceName := iface.Name()
+ ii := &InterfaceInfo{
@niemeyer

niemeyer Jul 25, 2017

Contributor

Let's please rename InterfaceInfo to Info. This is already interfaces.Info.

@zyga

zyga Jul 26, 2017

Contributor

Done

interfaces/repo.go
+ ifaceName := iface.Name()
+ ii := &InterfaceInfo{
+ Name: ifaceName,
+ MetaData: MetaData{Summary: md.Summary},
@niemeyer

niemeyer Jul 25, 2017

Contributor

And that's the Interface.Info.MetaData.Summary... ouch 😄

@zyga

zyga Jul 26, 2017

Contributor

Fixed :-)

interfaces/repo.go
+// If names is empty then all interfaces are considered. Query options decide
+// which data to return but can also skip interfaces without connections. See
+// the documentation of QueryOptions for details.
+func (r *Repository) QueryInterfaces(opts *QueryOptions) []*InterfaceInfo {
@niemeyer

niemeyer Jul 25, 2017

Contributor

This can be the Info method, taking InfoOptions in and returning []*interfaces.Info.

@zyga

zyga Jul 26, 2017

Contributor

Done

zyga added some commits Jul 26, 2017

client: use unnamed return values
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client,cmd: rename InterfaceQueryOptions to InterfaceOptions
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client: put each struct member on separate line
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client,cmd,daemon: use "true" over than "yes" for bool args
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
client,cmd: rename Interfaces (type) to Connections
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: combine label with plug/slot name
This patch changes "snap interface foo" to show the interface label
alongside plug/slot name. This makes the listing more compact and
pleasing, in absence of attributes to display (which is the default).

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: display attributes without extra header
This patch tweaks the way interface attributes are displayed so that the
extra word "attributes" is removed. This makes everything less nested
and nicer to read.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
cmd/snap: move check for x.ShowAttrs around
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: rename QueryOptions to InfoOptions
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: put each struct member on separate line
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: rename queryInterface to interfaceInfo
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: rename InterfaceInfo to just Info
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces,daemon: rename QueryInterfaces to just Info
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: inline relevant parts of MetaData into Info
The Summary and DocURL fields are now present directly in the Info
structure, not needing the indirection through MetaData. This is less
cluttered and aligns with client APIs closer.

In addition the change will allow renaming of MetaData to StaticInfo
without unnecessary influences on parts that don't concern it.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces: remove remnants of the Used field
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
interfaces,daemon,overlord: rename MetaData to StaticInfo
There is a lot of meta-data considering interfaces but some if it is
static and is baked into the binary. Let's give it an appropriate name.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Contributor

zyga commented Jul 26, 2017

Merging, the issue is unrelated to the PR (likely master broke with the release of stable core snap)

@zyga zyga merged commit bf28721 into snapcore:master Jul 26, 2017

1 of 7 checks passed

artful-amd64 autopkgtest finished (failure)
Details
xenial-amd64 autopkgtest finished (failure)
Details
xenial-i386 autopkgtest finished (failure)
Details
xenial-ppc64el autopkgtest finished (failure)
Details
yakkety-amd64 autopkgtest finished (failure)
Details
zesty-amd64 autopkgtest finished (failure)
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@zyga zyga deleted the zyga:feature/interface-command branch Jul 26, 2017

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