github.com/rigado/snapd@v2.42.5-go-mod+incompatible/client/interfaces.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package client 21 22 import ( 23 "bytes" 24 "encoding/json" 25 "net/url" 26 "strings" 27 ) 28 29 // Plug represents the potential of a given snap to connect to a slot. 30 type Plug struct { 31 Snap string `json:"snap"` 32 Name string `json:"plug"` 33 Interface string `json:"interface,omitempty"` 34 Attrs map[string]interface{} `json:"attrs,omitempty"` 35 Apps []string `json:"apps,omitempty"` 36 Label string `json:"label,omitempty"` 37 Connections []SlotRef `json:"connections,omitempty"` 38 } 39 40 // PlugRef is a reference to a plug. 41 type PlugRef struct { 42 Snap string `json:"snap"` 43 Name string `json:"plug"` 44 } 45 46 // Slot represents a capacity offered by a snap. 47 type Slot struct { 48 Snap string `json:"snap"` 49 Name string `json:"slot"` 50 Interface string `json:"interface,omitempty"` 51 Attrs map[string]interface{} `json:"attrs,omitempty"` 52 Apps []string `json:"apps,omitempty"` 53 Label string `json:"label,omitempty"` 54 Connections []PlugRef `json:"connections,omitempty"` 55 } 56 57 // SlotRef is a reference to a slot. 58 type SlotRef struct { 59 Snap string `json:"snap"` 60 Name string `json:"slot"` 61 } 62 63 // Interface holds information about a given interface and its instances. 64 type Interface struct { 65 Name string `json:"name,omitempty"` 66 Summary string `json:"summary,omitempty"` 67 DocURL string `json:"doc-url,omitempty"` 68 Plugs []Plug `json:"plugs,omitempty"` 69 Slots []Slot `json:"slots,omitempty"` 70 } 71 72 // InterfaceAction represents an action performed on the interface system. 73 type InterfaceAction struct { 74 Action string `json:"action"` 75 Plugs []Plug `json:"plugs,omitempty"` 76 Slots []Slot `json:"slots,omitempty"` 77 } 78 79 // InterfaceOptions represents opt-in elements include in responses. 80 type InterfaceOptions struct { 81 Names []string 82 Doc bool 83 Plugs bool 84 Slots bool 85 Connected bool 86 } 87 88 func (client *Client) Interfaces(opts *InterfaceOptions) ([]*Interface, error) { 89 query := url.Values{} 90 if opts != nil && len(opts.Names) > 0 { 91 query.Set("names", strings.Join(opts.Names, ",")) // Return just those specific interfaces. 92 } 93 if opts != nil { 94 if opts.Doc { 95 query.Set("doc", "true") // Return documentation of each selected interface. 96 } 97 if opts.Plugs { 98 query.Set("plugs", "true") // Return plugs of each selected interface. 99 } 100 if opts.Slots { 101 query.Set("slots", "true") // Return slots of each selected interface. 102 } 103 } 104 // NOTE: Presence of "select" triggers the use of the new response format. 105 if opts != nil && opts.Connected { 106 query.Set("select", "connected") // Return just the connected interfaces. 107 } else { 108 query.Set("select", "all") // Return all interfaces. 109 } 110 var interfaces []*Interface 111 _, err := client.doSync("GET", "/v2/interfaces", query, nil, nil, &interfaces) 112 113 return interfaces, err 114 } 115 116 // performInterfaceAction performs a single action on the interface system. 117 func (client *Client) performInterfaceAction(sa *InterfaceAction) (changeID string, err error) { 118 b, err := json.Marshal(sa) 119 if err != nil { 120 return "", err 121 } 122 return client.doAsync("POST", "/v2/interfaces", nil, nil, bytes.NewReader(b)) 123 } 124 125 // Connect establishes a connection between a plug and a slot. 126 // The plug and the slot must have the same interface. 127 func (client *Client) Connect(plugSnapName, plugName, slotSnapName, slotName string) (changeID string, err error) { 128 return client.performInterfaceAction(&InterfaceAction{ 129 Action: "connect", 130 Plugs: []Plug{{Snap: plugSnapName, Name: plugName}}, 131 Slots: []Slot{{Snap: slotSnapName, Name: slotName}}, 132 }) 133 } 134 135 // Disconnect breaks the connection between a plug and a slot. 136 func (client *Client) Disconnect(plugSnapName, plugName, slotSnapName, slotName string) (changeID string, err error) { 137 return client.performInterfaceAction(&InterfaceAction{ 138 Action: "disconnect", 139 Plugs: []Plug{{Snap: plugSnapName, Name: plugName}}, 140 Slots: []Slot{{Snap: slotSnapName, Name: slotName}}, 141 }) 142 }