Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ |
|
| 5 |
+ "github.com/docker/docker/api/types" |
|
| 6 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 7 |
+ "golang.org/x/net/context" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// ConfigCreate creates a new Config. |
|
| 11 |
+func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
|
| 12 |
+ var response types.ConfigCreateResponse |
|
| 13 |
+ resp, err := cli.post(ctx, "/configs/create", nil, config, nil) |
|
| 14 |
+ if err != nil {
|
|
| 15 |
+ return response, err |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ err = json.NewDecoder(resp.body).Decode(&response) |
|
| 19 |
+ ensureReaderClosed(resp) |
|
| 20 |
+ return response, err |
|
| 21 |
+} |
| 0 | 22 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,57 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/json" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io/ioutil" |
|
| 7 |
+ "net/http" |
|
| 8 |
+ "strings" |
|
| 9 |
+ "testing" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/docker/docker/api/types" |
|
| 12 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 13 |
+ "golang.org/x/net/context" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func TestConfigCreateError(t *testing.T) {
|
|
| 17 |
+ client := &Client{
|
|
| 18 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 19 |
+ } |
|
| 20 |
+ _, err := client.ConfigCreate(context.Background(), swarm.ConfigSpec{})
|
|
| 21 |
+ if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 22 |
+ t.Fatalf("expected a Server Error, got %v", err)
|
|
| 23 |
+ } |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func TestConfigCreate(t *testing.T) {
|
|
| 27 |
+ expectedURL := "/configs/create" |
|
| 28 |
+ client := &Client{
|
|
| 29 |
+ client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
|
| 30 |
+ if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
|
| 31 |
+ return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
|
| 32 |
+ } |
|
| 33 |
+ if req.Method != "POST" {
|
|
| 34 |
+ return nil, fmt.Errorf("expected POST method, got %s", req.Method)
|
|
| 35 |
+ } |
|
| 36 |
+ b, err := json.Marshal(types.ConfigCreateResponse{
|
|
| 37 |
+ ID: "test_config", |
|
| 38 |
+ }) |
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ return nil, err |
|
| 41 |
+ } |
|
| 42 |
+ return &http.Response{
|
|
| 43 |
+ StatusCode: http.StatusCreated, |
|
| 44 |
+ Body: ioutil.NopCloser(bytes.NewReader(b)), |
|
| 45 |
+ }, nil |
|
| 46 |
+ }), |
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ r, err := client.ConfigCreate(context.Background(), swarm.ConfigSpec{})
|
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ t.Fatal(err) |
|
| 52 |
+ } |
|
| 53 |
+ if r.ID != "test_config" {
|
|
| 54 |
+ t.Fatalf("expected `test_config`, got %s", r.ID)
|
|
| 55 |
+ } |
|
| 56 |
+} |
| 0 | 57 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,34 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/json" |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "net/http" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 9 |
+ "golang.org/x/net/context" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// ConfigInspectWithRaw returns the config information with raw data |
|
| 13 |
+func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) {
|
|
| 14 |
+ resp, err := cli.get(ctx, "/configs/"+id, nil, nil) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ if resp.statusCode == http.StatusNotFound {
|
|
| 17 |
+ return swarm.Config{}, nil, configNotFoundError{id}
|
|
| 18 |
+ } |
|
| 19 |
+ return swarm.Config{}, nil, err
|
|
| 20 |
+ } |
|
| 21 |
+ defer ensureReaderClosed(resp) |
|
| 22 |
+ |
|
| 23 |
+ body, err := ioutil.ReadAll(resp.body) |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return swarm.Config{}, nil, err
|
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ var config swarm.Config |
|
| 29 |
+ rdr := bytes.NewReader(body) |
|
| 30 |
+ err = json.NewDecoder(rdr).Decode(&config) |
|
| 31 |
+ |
|
| 32 |
+ return config, body, err |
|
| 33 |
+} |
| 0 | 34 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,65 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/json" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io/ioutil" |
|
| 7 |
+ "net/http" |
|
| 8 |
+ "strings" |
|
| 9 |
+ "testing" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 12 |
+ "golang.org/x/net/context" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+func TestConfigInspectError(t *testing.T) {
|
|
| 16 |
+ client := &Client{
|
|
| 17 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ _, _, err := client.ConfigInspectWithRaw(context.Background(), "nothing") |
|
| 21 |
+ if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 22 |
+ t.Fatalf("expected a Server Error, got %v", err)
|
|
| 23 |
+ } |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func TestConfigInspectConfigNotFound(t *testing.T) {
|
|
| 27 |
+ client := &Client{
|
|
| 28 |
+ client: newMockClient(errorMock(http.StatusNotFound, "Server error")), |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 31 |
+ _, _, err := client.ConfigInspectWithRaw(context.Background(), "unknown") |
|
| 32 |
+ if err == nil || !IsErrConfigNotFound(err) {
|
|
| 33 |
+ t.Fatalf("expected a configNotFoundError error, got %v", err)
|
|
| 34 |
+ } |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func TestConfigInspect(t *testing.T) {
|
|
| 38 |
+ expectedURL := "/configs/config_id" |
|
| 39 |
+ client := &Client{
|
|
| 40 |
+ client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
|
| 41 |
+ if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
|
| 42 |
+ return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
|
| 43 |
+ } |
|
| 44 |
+ content, err := json.Marshal(swarm.Config{
|
|
| 45 |
+ ID: "config_id", |
|
| 46 |
+ }) |
|
| 47 |
+ if err != nil {
|
|
| 48 |
+ return nil, err |
|
| 49 |
+ } |
|
| 50 |
+ return &http.Response{
|
|
| 51 |
+ StatusCode: http.StatusOK, |
|
| 52 |
+ Body: ioutil.NopCloser(bytes.NewReader(content)), |
|
| 53 |
+ }, nil |
|
| 54 |
+ }), |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ configInspect, _, err := client.ConfigInspectWithRaw(context.Background(), "config_id") |
|
| 58 |
+ if err != nil {
|
|
| 59 |
+ t.Fatal(err) |
|
| 60 |
+ } |
|
| 61 |
+ if configInspect.ID != "config_id" {
|
|
| 62 |
+ t.Fatalf("expected `config_id`, got %s", configInspect.ID)
|
|
| 63 |
+ } |
|
| 64 |
+} |
| 0 | 65 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,35 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "net/url" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/docker/api/types" |
|
| 7 |
+ "github.com/docker/docker/api/types/filters" |
|
| 8 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 9 |
+ "golang.org/x/net/context" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// ConfigList returns the list of configs. |
|
| 13 |
+func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
|
| 14 |
+ query := url.Values{}
|
|
| 15 |
+ |
|
| 16 |
+ if options.Filters.Len() > 0 {
|
|
| 17 |
+ filterJSON, err := filters.ToParam(options.Filters) |
|
| 18 |
+ if err != nil {
|
|
| 19 |
+ return nil, err |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ query.Set("filters", filterJSON)
|
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ resp, err := cli.get(ctx, "/configs", query, nil) |
|
| 26 |
+ if err != nil {
|
|
| 27 |
+ return nil, err |
|
| 28 |
+ } |
|
| 29 |
+ |
|
| 30 |
+ var configs []swarm.Config |
|
| 31 |
+ err = json.NewDecoder(resp.body).Decode(&configs) |
|
| 32 |
+ ensureReaderClosed(resp) |
|
| 33 |
+ return configs, err |
|
| 34 |
+} |
| 0 | 35 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,94 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/json" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io/ioutil" |
|
| 7 |
+ "net/http" |
|
| 8 |
+ "strings" |
|
| 9 |
+ "testing" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/docker/docker/api/types" |
|
| 12 |
+ "github.com/docker/docker/api/types/filters" |
|
| 13 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 14 |
+ "golang.org/x/net/context" |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+func TestConfigListError(t *testing.T) {
|
|
| 18 |
+ client := &Client{
|
|
| 19 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ _, err := client.ConfigList(context.Background(), types.ConfigListOptions{})
|
|
| 23 |
+ if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 24 |
+ t.Fatalf("expected a Server Error, got %v", err)
|
|
| 25 |
+ } |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+func TestConfigList(t *testing.T) {
|
|
| 29 |
+ expectedURL := "/configs" |
|
| 30 |
+ |
|
| 31 |
+ filters := filters.NewArgs() |
|
| 32 |
+ filters.Add("label", "label1")
|
|
| 33 |
+ filters.Add("label", "label2")
|
|
| 34 |
+ |
|
| 35 |
+ listCases := []struct {
|
|
| 36 |
+ options types.ConfigListOptions |
|
| 37 |
+ expectedQueryParams map[string]string |
|
| 38 |
+ }{
|
|
| 39 |
+ {
|
|
| 40 |
+ options: types.ConfigListOptions{},
|
|
| 41 |
+ expectedQueryParams: map[string]string{
|
|
| 42 |
+ "filters": "", |
|
| 43 |
+ }, |
|
| 44 |
+ }, |
|
| 45 |
+ {
|
|
| 46 |
+ options: types.ConfigListOptions{
|
|
| 47 |
+ Filters: filters, |
|
| 48 |
+ }, |
|
| 49 |
+ expectedQueryParams: map[string]string{
|
|
| 50 |
+ "filters": `{"label":{"label1":true,"label2":true}}`,
|
|
| 51 |
+ }, |
|
| 52 |
+ }, |
|
| 53 |
+ } |
|
| 54 |
+ for _, listCase := range listCases {
|
|
| 55 |
+ client := &Client{
|
|
| 56 |
+ client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
|
| 57 |
+ if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
|
| 58 |
+ return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
|
| 59 |
+ } |
|
| 60 |
+ query := req.URL.Query() |
|
| 61 |
+ for key, expected := range listCase.expectedQueryParams {
|
|
| 62 |
+ actual := query.Get(key) |
|
| 63 |
+ if actual != expected {
|
|
| 64 |
+ return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
|
|
| 65 |
+ } |
|
| 66 |
+ } |
|
| 67 |
+ content, err := json.Marshal([]swarm.Config{
|
|
| 68 |
+ {
|
|
| 69 |
+ ID: "config_id1", |
|
| 70 |
+ }, |
|
| 71 |
+ {
|
|
| 72 |
+ ID: "config_id2", |
|
| 73 |
+ }, |
|
| 74 |
+ }) |
|
| 75 |
+ if err != nil {
|
|
| 76 |
+ return nil, err |
|
| 77 |
+ } |
|
| 78 |
+ return &http.Response{
|
|
| 79 |
+ StatusCode: http.StatusOK, |
|
| 80 |
+ Body: ioutil.NopCloser(bytes.NewReader(content)), |
|
| 81 |
+ }, nil |
|
| 82 |
+ }), |
|
| 83 |
+ } |
|
| 84 |
+ |
|
| 85 |
+ configs, err := client.ConfigList(context.Background(), listCase.options) |
|
| 86 |
+ if err != nil {
|
|
| 87 |
+ t.Fatal(err) |
|
| 88 |
+ } |
|
| 89 |
+ if len(configs) != 2 {
|
|
| 90 |
+ t.Fatalf("expected 2 configs, got %v", configs)
|
|
| 91 |
+ } |
|
| 92 |
+ } |
|
| 93 |
+} |
| 0 | 94 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,10 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import "golang.org/x/net/context" |
|
| 3 |
+ |
|
| 4 |
+// ConfigRemove removes a Config. |
|
| 5 |
+func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
|
|
| 6 |
+ resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) |
|
| 7 |
+ ensureReaderClosed(resp) |
|
| 8 |
+ return err |
|
| 9 |
+} |
| 0 | 10 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,47 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "net/http" |
|
| 7 |
+ "strings" |
|
| 8 |
+ "testing" |
|
| 9 |
+ |
|
| 10 |
+ "golang.org/x/net/context" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func TestConfigRemoveError(t *testing.T) {
|
|
| 14 |
+ client := &Client{
|
|
| 15 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ err := client.ConfigRemove(context.Background(), "config_id") |
|
| 19 |
+ if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 20 |
+ t.Fatalf("expected a Server Error, got %v", err)
|
|
| 21 |
+ } |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func TestConfigRemove(t *testing.T) {
|
|
| 25 |
+ expectedURL := "/configs/config_id" |
|
| 26 |
+ |
|
| 27 |
+ client := &Client{
|
|
| 28 |
+ client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
|
| 29 |
+ if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
|
| 30 |
+ return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
|
| 31 |
+ } |
|
| 32 |
+ if req.Method != "DELETE" {
|
|
| 33 |
+ return nil, fmt.Errorf("expected DELETE method, got %s", req.Method)
|
|
| 34 |
+ } |
|
| 35 |
+ return &http.Response{
|
|
| 36 |
+ StatusCode: http.StatusOK, |
|
| 37 |
+ Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
|
|
| 38 |
+ }, nil |
|
| 39 |
+ }), |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ err := client.ConfigRemove(context.Background(), "config_id") |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ t.Fatal(err) |
|
| 45 |
+ } |
|
| 46 |
+} |
| 0 | 47 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "net/url" |
|
| 4 |
+ "strconv" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 7 |
+ "golang.org/x/net/context" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// ConfigUpdate attempts to updates a Config |
|
| 11 |
+func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error {
|
|
| 12 |
+ query := url.Values{}
|
|
| 13 |
+ query.Set("version", strconv.FormatUint(version.Index, 10))
|
|
| 14 |
+ resp, err := cli.post(ctx, "/configs/"+id+"/update", query, config, nil) |
|
| 15 |
+ ensureReaderClosed(resp) |
|
| 16 |
+ return err |
|
| 17 |
+} |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,49 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "net/http" |
|
| 7 |
+ "strings" |
|
| 8 |
+ "testing" |
|
| 9 |
+ |
|
| 10 |
+ "golang.org/x/net/context" |
|
| 11 |
+ |
|
| 12 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+func TestConfigUpdateError(t *testing.T) {
|
|
| 16 |
+ client := &Client{
|
|
| 17 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ err := client.ConfigUpdate(context.Background(), "config_id", swarm.Version{}, swarm.ConfigSpec{})
|
|
| 21 |
+ if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 22 |
+ t.Fatalf("expected a Server Error, got %v", err)
|
|
| 23 |
+ } |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func TestConfigUpdate(t *testing.T) {
|
|
| 27 |
+ expectedURL := "/configs/config_id/update" |
|
| 28 |
+ |
|
| 29 |
+ client := &Client{
|
|
| 30 |
+ client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
|
| 31 |
+ if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
|
| 32 |
+ return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
|
| 33 |
+ } |
|
| 34 |
+ if req.Method != "POST" {
|
|
| 35 |
+ return nil, fmt.Errorf("expected POST method, got %s", req.Method)
|
|
| 36 |
+ } |
|
| 37 |
+ return &http.Response{
|
|
| 38 |
+ StatusCode: http.StatusOK, |
|
| 39 |
+ Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
|
|
| 40 |
+ }, nil |
|
| 41 |
+ }), |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ err := client.ConfigUpdate(context.Background(), "config_id", swarm.Version{}, swarm.ConfigSpec{})
|
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ t.Fatal(err) |
|
| 47 |
+ } |
|
| 48 |
+} |
| ... | ... |
@@ -256,6 +256,28 @@ func IsErrSecretNotFound(err error) bool {
|
| 256 | 256 |
return ok |
| 257 | 257 |
} |
| 258 | 258 |
|
| 259 |
+// configNotFoundError implements an error returned when a config is not found. |
|
| 260 |
+type configNotFoundError struct {
|
|
| 261 |
+ name string |
|
| 262 |
+} |
|
| 263 |
+ |
|
| 264 |
+// Error returns a string representation of a configNotFoundError |
|
| 265 |
+func (e configNotFoundError) Error() string {
|
|
| 266 |
+ return fmt.Sprintf("Error: no such config: %s", e.name)
|
|
| 267 |
+} |
|
| 268 |
+ |
|
| 269 |
+// NotFound indicates that this error type is of NotFound |
|
| 270 |
+func (e configNotFoundError) NotFound() bool {
|
|
| 271 |
+ return true |
|
| 272 |
+} |
|
| 273 |
+ |
|
| 274 |
+// IsErrConfigNotFound returns true if the error is caused |
|
| 275 |
+// when a config is not found. |
|
| 276 |
+func IsErrConfigNotFound(err error) bool {
|
|
| 277 |
+ _, ok := err.(configNotFoundError) |
|
| 278 |
+ return ok |
|
| 279 |
+} |
|
| 280 |
+ |
|
| 259 | 281 |
// pluginNotFoundError implements an error returned when a plugin is not in the docker host. |
| 260 | 282 |
type pluginNotFoundError struct {
|
| 261 | 283 |
name string |
| ... | ... |
@@ -18,6 +18,7 @@ import ( |
| 18 | 18 |
|
| 19 | 19 |
// CommonAPIClient is the common methods between stable and experimental versions of APIClient. |
| 20 | 20 |
type CommonAPIClient interface {
|
| 21 |
+ ConfigAPIClient |
|
| 21 | 22 |
ContainerAPIClient |
| 22 | 23 |
ImageAPIClient |
| 23 | 24 |
NodeAPIClient |
| ... | ... |
@@ -171,3 +172,12 @@ type SecretAPIClient interface {
|
| 171 | 171 |
SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error) |
| 172 | 172 |
SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error |
| 173 | 173 |
} |
| 174 |
+ |
|
| 175 |
+// ConfigAPIClient defines API client methods for configs |
|
| 176 |
+type ConfigAPIClient interface {
|
|
| 177 |
+ ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) |
|
| 178 |
+ ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) |
|
| 179 |
+ ConfigRemove(ctx context.Context, id string) error |
|
| 180 |
+ ConfigInspectWithRaw(ctx context.Context, name string) (swarm.Config, []byte, error) |
|
| 181 |
+ ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error |
|
| 182 |
+} |