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  }