104 lines
2.4 KiB
Go
104 lines
2.4 KiB
Go
|
package client
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"net/http"
|
||
|
"syscall"
|
||
|
"time"
|
||
|
|
||
|
"github.com/kubernetes-incubator/cri-o/types"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
|
||
|
)
|
||
|
|
||
|
// CrioClient is an interface to get information from crio daemon endpoint.
|
||
|
type CrioClient interface {
|
||
|
DaemonInfo() (types.CrioInfo, error)
|
||
|
ContainerInfo(string) (*types.ContainerInfo, error)
|
||
|
}
|
||
|
|
||
|
type crioClientImpl struct {
|
||
|
client *http.Client
|
||
|
crioSocketPath string
|
||
|
}
|
||
|
|
||
|
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
|
||
|
if len(addr) > maxUnixSocketPathSize {
|
||
|
return fmt.Errorf("Unix socket path %q is too long", addr)
|
||
|
}
|
||
|
// No need for compression in local communications.
|
||
|
tr.DisableCompression = true
|
||
|
tr.Dial = func(_, _ string) (net.Conn, error) {
|
||
|
return net.DialTimeout(proto, addr, 32*time.Second)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// New returns a crio client
|
||
|
func New(crioSocketPath string) (CrioClient, error) {
|
||
|
tr := new(http.Transport)
|
||
|
configureUnixTransport(tr, "unix", crioSocketPath)
|
||
|
c := &http.Client{
|
||
|
Transport: tr,
|
||
|
}
|
||
|
return &crioClientImpl{
|
||
|
client: c,
|
||
|
crioSocketPath: crioSocketPath,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (c *crioClientImpl) getRequest(path string) (*http.Request, error) {
|
||
|
req, err := http.NewRequest("GET", path, nil)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
// For local communications over a unix socket, it doesn't matter what
|
||
|
// the host is. We just need a valid and meaningful host name.
|
||
|
req.Host = "crio"
|
||
|
req.URL.Host = c.crioSocketPath
|
||
|
req.URL.Scheme = "http"
|
||
|
return req, nil
|
||
|
}
|
||
|
|
||
|
// DaemonInfo return cri-o daemon info from the cri-o
|
||
|
// info endpoint.
|
||
|
func (c *crioClientImpl) DaemonInfo() (types.CrioInfo, error) {
|
||
|
info := types.CrioInfo{}
|
||
|
req, err := c.getRequest("/info")
|
||
|
if err != nil {
|
||
|
return info, err
|
||
|
}
|
||
|
resp, err := c.client.Do(req)
|
||
|
if err != nil {
|
||
|
return info, err
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
|
||
|
return info, err
|
||
|
}
|
||
|
return info, nil
|
||
|
}
|
||
|
|
||
|
// ContainerInfo returns container info by querying
|
||
|
// the cri-o container endpoint.
|
||
|
func (c *crioClientImpl) ContainerInfo(id string) (*types.ContainerInfo, error) {
|
||
|
req, err := c.getRequest("/containers/" + id)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
resp, err := c.client.Do(req)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
cInfo := types.ContainerInfo{}
|
||
|
if err := json.NewDecoder(resp.Body).Decode(&cInfo); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return &cInfo, nil
|
||
|
}
|