client.go 3.4 KB

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