1// Copyright 2017 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	"net/http"
11	"net/url"
12	"strconv"
13
14	"github.com/docker/docker/api/types/swarm"
15)
16
17// NoSuchConfig is the error returned when a given config does not exist.
18type NoSuchConfig struct {
19	ID  string
20	Err error
21}
22
23func (err *NoSuchConfig) Error() string {
24	if err.Err != nil {
25		return err.Err.Error()
26	}
27	return "No such config: " + err.ID
28}
29
30// CreateConfigOptions specify parameters to the CreateConfig function.
31//
32// See https://goo.gl/KrVjHz for more details.
33type CreateConfigOptions struct {
34	Auth AuthConfiguration `qs:"-"`
35	swarm.ConfigSpec
36	Context context.Context
37}
38
39// CreateConfig creates a new config, returning the config instance
40// or an error in case of failure.
41//
42// See https://goo.gl/KrVjHz for more details.
43func (c *Client) CreateConfig(opts CreateConfigOptions) (*swarm.Config, error) {
44	headers, err := headersWithAuth(opts.Auth)
45	if err != nil {
46		return nil, err
47	}
48	path := "/configs/create?" + queryString(opts)
49	resp, err := c.do("POST", path, doOptions{
50		headers:   headers,
51		data:      opts.ConfigSpec,
52		forceJSON: true,
53		context:   opts.Context,
54	})
55	if err != nil {
56		return nil, err
57	}
58	defer resp.Body.Close()
59	var config swarm.Config
60	if err := json.NewDecoder(resp.Body).Decode(&config); err != nil {
61		return nil, err
62	}
63	return &config, nil
64}
65
66// RemoveConfigOptions encapsulates options to remove a config.
67//
68// See https://goo.gl/Tqrtya for more details.
69type RemoveConfigOptions struct {
70	ID      string `qs:"-"`
71	Context context.Context
72}
73
74// RemoveConfig removes a config, returning an error in case of failure.
75//
76// See https://goo.gl/Tqrtya for more details.
77func (c *Client) RemoveConfig(opts RemoveConfigOptions) error {
78	path := "/configs/" + opts.ID
79	resp, err := c.do("DELETE", path, doOptions{context: opts.Context})
80	if err != nil {
81		if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
82			return &NoSuchConfig{ID: opts.ID}
83		}
84		return err
85	}
86	resp.Body.Close()
87	return nil
88}
89
90// UpdateConfigOptions specify parameters to the UpdateConfig function.
91//
92// See https://goo.gl/wu3MmS for more details.
93type UpdateConfigOptions struct {
94	Auth AuthConfiguration `qs:"-"`
95	swarm.ConfigSpec
96	Context context.Context
97	Version uint64
98}
99
100// UpdateConfig updates the config at ID with the options
101//
102// Only label can be updated
103// https://docs.docker.com/engine/api/v1.33/#operation/ConfigUpdate
104// See https://goo.gl/wu3MmS for more details.
105func (c *Client) UpdateConfig(id string, opts UpdateConfigOptions) error {
106	headers, err := headersWithAuth(opts.Auth)
107	if err != nil {
108		return err
109	}
110	params := make(url.Values)
111	params.Set("version", strconv.FormatUint(opts.Version, 10))
112	resp, err := c.do("POST", "/configs/"+id+"/update?"+params.Encode(), doOptions{
113		headers:   headers,
114		data:      opts.ConfigSpec,
115		forceJSON: true,
116		context:   opts.Context,
117	})
118	if err != nil {
119		if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
120			return &NoSuchConfig{ID: id}
121		}
122		return err
123	}
124	defer resp.Body.Close()
125	return nil
126}
127
128// InspectConfig returns information about a config by its ID.
129//
130// See https://goo.gl/dHmr75 for more details.
131func (c *Client) InspectConfig(id string) (*swarm.Config, error) {
132	path := "/configs/" + id
133	resp, err := c.do("GET", path, doOptions{})
134	if err != nil {
135		if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
136			return nil, &NoSuchConfig{ID: id}
137		}
138		return nil, err
139	}
140	defer resp.Body.Close()
141	var config swarm.Config
142	if err := json.NewDecoder(resp.Body).Decode(&config); err != nil {
143		return nil, err
144	}
145	return &config, nil
146}
147
148// ListConfigsOptions specify parameters to the ListConfigs function.
149//
150// See https://goo.gl/DwvNMd for more details.
151type ListConfigsOptions struct {
152	Filters map[string][]string
153	Context context.Context
154}
155
156// ListConfigs returns a slice of configs matching the given criteria.
157//
158// See https://goo.gl/DwvNMd for more details.
159func (c *Client) ListConfigs(opts ListConfigsOptions) ([]swarm.Config, error) {
160	path := "/configs?" + queryString(opts)
161	resp, err := c.do("GET", path, doOptions{context: opts.Context})
162	if err != nil {
163		return nil, err
164	}
165	defer resp.Body.Close()
166	var configs []swarm.Config
167	if err := json.NewDecoder(resp.Body).Decode(&configs); err != nil {
168		return nil, err
169	}
170	return configs, nil
171}
172