podman
218 строк · 5.9 Кб
1// Copyright 2016 go-dockerclient authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package docker
6
7import (
8"context"
9"encoding/json"
10"errors"
11"io"
12"net/http"
13"time"
14
15"github.com/docker/docker/api/types/swarm"
16)
17
18// NoSuchService is the error returned when a given service does not exist.
19type NoSuchService struct {
20ID string
21Err error
22}
23
24func (err *NoSuchService) Error() string {
25if err.Err != nil {
26return err.Err.Error()
27}
28return "No such service: " + err.ID
29}
30
31// CreateServiceOptions specify parameters to the CreateService function.
32//
33// See https://goo.gl/KrVjHz for more details.
34type CreateServiceOptions struct {
35Auth AuthConfiguration `qs:"-"`
36swarm.ServiceSpec
37Context context.Context
38}
39
40// CreateService creates a new service, returning the service instance
41// or an error in case of failure.
42//
43// See https://goo.gl/KrVjHz for more details.
44func (c *Client) CreateService(opts CreateServiceOptions) (*swarm.Service, error) {
45headers, err := headersWithAuth(opts.Auth)
46if err != nil {
47return nil, err
48}
49path := "/services/create?" + queryString(opts)
50resp, err := c.do(http.MethodPost, path, doOptions{
51headers: headers,
52data: opts.ServiceSpec,
53forceJSON: true,
54context: opts.Context,
55})
56if err != nil {
57return nil, err
58}
59defer resp.Body.Close()
60var service swarm.Service
61if err := json.NewDecoder(resp.Body).Decode(&service); err != nil {
62return nil, err
63}
64return &service, nil
65}
66
67// RemoveServiceOptions encapsulates options to remove a service.
68//
69// See https://goo.gl/Tqrtya for more details.
70type RemoveServiceOptions struct {
71ID string `qs:"-"`
72Context context.Context
73}
74
75// RemoveService removes a service, returning an error in case of failure.
76//
77// See https://goo.gl/Tqrtya for more details.
78func (c *Client) RemoveService(opts RemoveServiceOptions) error {
79path := "/services/" + opts.ID
80resp, err := c.do(http.MethodDelete, path, doOptions{context: opts.Context})
81if err != nil {
82var e *Error
83if errors.As(err, &e) && e.Status == http.StatusNotFound {
84return &NoSuchService{ID: opts.ID}
85}
86return err
87}
88resp.Body.Close()
89return nil
90}
91
92// UpdateServiceOptions specify parameters to the UpdateService function.
93//
94// See https://goo.gl/wu3MmS for more details.
95type UpdateServiceOptions struct {
96Auth AuthConfiguration `qs:"-"`
97swarm.ServiceSpec `qs:"-"`
98Context context.Context
99Version uint64
100Rollback string
101}
102
103// UpdateService updates the service at ID with the options
104//
105// See https://goo.gl/wu3MmS for more details.
106func (c *Client) UpdateService(id string, opts UpdateServiceOptions) error {
107headers, err := headersWithAuth(opts.Auth)
108if err != nil {
109return err
110}
111resp, err := c.do(http.MethodPost, "/services/"+id+"/update?"+queryString(opts), doOptions{
112headers: headers,
113data: opts.ServiceSpec,
114forceJSON: true,
115context: opts.Context,
116})
117if err != nil {
118var e *Error
119if errors.As(err, &e) && e.Status == http.StatusNotFound {
120return &NoSuchService{ID: id}
121}
122return err
123}
124defer resp.Body.Close()
125return nil
126}
127
128// InspectService returns information about a service by its ID.
129//
130// See https://goo.gl/dHmr75 for more details.
131func (c *Client) InspectService(id string) (*swarm.Service, error) {
132path := "/services/" + id
133resp, err := c.do(http.MethodGet, path, doOptions{})
134if err != nil {
135var e *Error
136if errors.As(err, &e) && e.Status == http.StatusNotFound {
137return nil, &NoSuchService{ID: id}
138}
139return nil, err
140}
141defer resp.Body.Close()
142var service swarm.Service
143if err := json.NewDecoder(resp.Body).Decode(&service); err != nil {
144return nil, err
145}
146return &service, nil
147}
148
149// ListServicesOptions specify parameters to the ListServices function.
150//
151// See https://goo.gl/DwvNMd for more details.
152type ListServicesOptions struct {
153Filters map[string][]string
154Status bool
155Context context.Context
156}
157
158// ListServices returns a slice of services matching the given criteria.
159//
160// See https://goo.gl/DwvNMd for more details.
161func (c *Client) ListServices(opts ListServicesOptions) ([]swarm.Service, error) {
162path := "/services?" + queryString(opts)
163resp, err := c.do(http.MethodGet, path, doOptions{context: opts.Context})
164if err != nil {
165return nil, err
166}
167defer resp.Body.Close()
168var services []swarm.Service
169if err := json.NewDecoder(resp.Body).Decode(&services); err != nil {
170return nil, err
171}
172return services, nil
173}
174
175// LogsServiceOptions represents the set of options used when getting logs from a
176// service.
177type LogsServiceOptions struct {
178Context context.Context
179Service string `qs:"-"`
180OutputStream io.Writer `qs:"-"`
181ErrorStream io.Writer `qs:"-"`
182InactivityTimeout time.Duration `qs:"-"`
183Tail string
184Since int64
185
186// Use raw terminal? Usually true when the container contains a TTY.
187RawTerminal bool `qs:"-"`
188Follow bool
189Stdout bool
190Stderr bool
191Timestamps bool
192Details bool
193}
194
195// GetServiceLogs gets stdout and stderr logs from the specified service.
196//
197// When LogsServiceOptions.RawTerminal is set to false, go-dockerclient will multiplex
198// the streams and send the containers stdout to LogsServiceOptions.OutputStream, and
199// stderr to LogsServiceOptions.ErrorStream.
200//
201// When LogsServiceOptions.RawTerminal is true, callers will get the raw stream on
202// LogsServiceOptions.OutputStream.
203func (c *Client) GetServiceLogs(opts LogsServiceOptions) error {
204if opts.Service == "" {
205return &NoSuchService{ID: opts.Service}
206}
207if opts.Tail == "" {
208opts.Tail = "all"
209}
210path := "/services/" + opts.Service + "/logs?" + queryString(opts)
211return c.stream(http.MethodGet, path, streamOptions{
212setRawTerminal: opts.RawTerminal,
213stdout: opts.OutputStream,
214stderr: opts.ErrorStream,
215inactivityTimeout: opts.InactivityTimeout,
216context: opts.Context,
217})
218}
219