github.com/rootless-containers/rootlesskit/v2@v2.3.4/pkg/api/client/client.go (about)

     1  package client
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"fmt"
     8  	"net/http"
     9  
    10  	"github.com/rootless-containers/rootlesskit/v2/pkg/api"
    11  	"github.com/rootless-containers/rootlesskit/v2/pkg/httputil"
    12  	"github.com/rootless-containers/rootlesskit/v2/pkg/port"
    13  )
    14  
    15  type Client interface {
    16  	HTTPClient() *http.Client
    17  	PortManager() port.Manager
    18  	Info(context.Context) (*api.Info, error)
    19  }
    20  
    21  // New creates a client.
    22  // socketPath is a path to the UNIX socket, without unix:// prefix.
    23  func New(socketPath string) (Client, error) {
    24  	hc, err := httputil.NewHTTPClient(socketPath)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	return NewWithHTTPClient(hc), nil
    29  }
    30  
    31  func NewWithHTTPClient(hc *http.Client) Client {
    32  	return &client{
    33  		Client:    hc,
    34  		version:   "v1",
    35  		dummyHost: "rootlesskit",
    36  	}
    37  }
    38  
    39  type client struct {
    40  	*http.Client
    41  	// version is always "v1"
    42  	// TODO(AkihiroSuda): negotiate the version
    43  	version   string
    44  	dummyHost string
    45  }
    46  
    47  func (c *client) HTTPClient() *http.Client {
    48  	return c.Client
    49  }
    50  
    51  func (c *client) PortManager() port.Manager {
    52  	return &portManager{
    53  		client: c,
    54  	}
    55  }
    56  
    57  func (c *client) Info(ctx context.Context) (*api.Info, error) {
    58  	u := fmt.Sprintf("http://%s/%s/info", c.dummyHost, c.version)
    59  	req, err := http.NewRequest("GET", u, nil)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	req = req.WithContext(ctx)
    64  	resp, err := c.HTTPClient().Do(req)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	defer resp.Body.Close()
    69  	if err := httputil.Successful(resp); err != nil {
    70  		return nil, err
    71  	}
    72  	var info api.Info
    73  	dec := json.NewDecoder(resp.Body)
    74  	if err := dec.Decode(&info); err != nil {
    75  		return nil, err
    76  	}
    77  	return &info, nil
    78  }
    79  
    80  type portManager struct {
    81  	*client
    82  }
    83  
    84  func (pm *portManager) AddPort(ctx context.Context, spec port.Spec) (*port.Status, error) {
    85  	m, err := json.Marshal(spec)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	u := fmt.Sprintf("http://%s/%s/ports", pm.client.dummyHost, pm.client.version)
    90  	req, err := http.NewRequest("POST", u, bytes.NewReader(m))
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	req.Header.Set("Content-Type", "application/json")
    95  	req = req.WithContext(ctx)
    96  	resp, err := pm.client.HTTPClient().Do(req)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	defer resp.Body.Close()
   101  	if err := httputil.Successful(resp); err != nil {
   102  		return nil, err
   103  	}
   104  	dec := json.NewDecoder(resp.Body)
   105  	var status port.Status
   106  	if err := dec.Decode(&status); err != nil {
   107  		return nil, err
   108  	}
   109  	return &status, nil
   110  }
   111  func (pm *portManager) ListPorts(ctx context.Context) ([]port.Status, error) {
   112  	u := fmt.Sprintf("http://%s/%s/ports", pm.client.dummyHost, pm.client.version)
   113  	req, err := http.NewRequest("GET", u, nil)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	req = req.WithContext(ctx)
   118  	resp, err := pm.client.HTTPClient().Do(req)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  	defer resp.Body.Close()
   123  	if err := httputil.Successful(resp); err != nil {
   124  		return nil, err
   125  	}
   126  	var statuses []port.Status
   127  	dec := json.NewDecoder(resp.Body)
   128  	if err := dec.Decode(&statuses); err != nil {
   129  		return nil, err
   130  	}
   131  	return statuses, nil
   132  }
   133  func (pm *portManager) RemovePort(ctx context.Context, id int) error {
   134  	u := fmt.Sprintf("http://%s/%s/ports/%d", pm.client.dummyHost, pm.client.version, id)
   135  	req, err := http.NewRequest("DELETE", u, nil)
   136  	if err != nil {
   137  		return err
   138  	}
   139  	req = req.WithContext(ctx)
   140  	resp, err := pm.client.HTTPClient().Do(req)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	defer resp.Body.Close()
   145  	if err := httputil.Successful(resp); err != nil {
   146  		return err
   147  	}
   148  	return nil
   149  }