// Copyright 2016 go-dockerclient authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package docker import ( "context" "encoding/json" "errors" "net/http" "net/url" "strconv" "github.com/docker/docker/api/types/swarm" ) // NoSuchSecret is the error returned when a given secret does not exist. type NoSuchSecret struct { ID string Err error } func (err *NoSuchSecret) Error() string { if err.Err != nil { return err.Err.Error() } return "No such secret: " + err.ID } // CreateSecretOptions specify parameters to the CreateSecret function. // // See https://goo.gl/KrVjHz for more details. type CreateSecretOptions struct { Auth AuthConfiguration `qs:"-"` swarm.SecretSpec Context context.Context } // CreateSecret creates a new secret, returning the secret instance // or an error in case of failure. // // See https://goo.gl/KrVjHz for more details. func (c *Client) CreateSecret(opts CreateSecretOptions) (*swarm.Secret, error) { headers, err := headersWithAuth(opts.Auth) if err != nil { return nil, err } path := "/secrets/create?" + queryString(opts) resp, err := c.do(http.MethodPost, path, doOptions{ headers: headers, data: opts.SecretSpec, forceJSON: true, context: opts.Context, }) if err != nil { return nil, err } defer resp.Body.Close() var secret swarm.Secret if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil { return nil, err } return &secret, nil } // RemoveSecretOptions encapsulates options to remove a secret. // // See https://goo.gl/Tqrtya for more details. type RemoveSecretOptions struct { ID string `qs:"-"` Context context.Context } // RemoveSecret removes a secret, returning an error in case of failure. // // See https://goo.gl/Tqrtya for more details. func (c *Client) RemoveSecret(opts RemoveSecretOptions) error { path := "/secrets/" + opts.ID resp, err := c.do(http.MethodDelete, path, doOptions{context: opts.Context}) if err != nil { var e *Error if errors.As(err, &e) && e.Status == http.StatusNotFound { return &NoSuchSecret{ID: opts.ID} } return err } resp.Body.Close() return nil } // UpdateSecretOptions specify parameters to the UpdateSecret function. // // Only label can be updated // See https://docs.docker.com/engine/api/v1.33/#operation/SecretUpdate // See https://goo.gl/wu3MmS for more details. type UpdateSecretOptions struct { Auth AuthConfiguration `qs:"-"` swarm.SecretSpec Context context.Context Version uint64 } // UpdateSecret updates the secret at ID with the options // // See https://goo.gl/wu3MmS for more details. func (c *Client) UpdateSecret(id string, opts UpdateSecretOptions) error { headers, err := headersWithAuth(opts.Auth) if err != nil { return err } params := make(url.Values) params.Set("version", strconv.FormatUint(opts.Version, 10)) resp, err := c.do(http.MethodPost, "/secrets/"+id+"/update?"+params.Encode(), doOptions{ headers: headers, data: opts.SecretSpec, forceJSON: true, context: opts.Context, }) if err != nil { var e *Error if errors.As(err, &e) && e.Status == http.StatusNotFound { return &NoSuchSecret{ID: id} } return err } defer resp.Body.Close() return nil } // InspectSecret returns information about a secret by its ID. // // See https://goo.gl/dHmr75 for more details. func (c *Client) InspectSecret(id string) (*swarm.Secret, error) { path := "/secrets/" + id resp, err := c.do(http.MethodGet, path, doOptions{}) if err != nil { var e *Error if errors.As(err, &e) && e.Status == http.StatusNotFound { return nil, &NoSuchSecret{ID: id} } return nil, err } defer resp.Body.Close() var secret swarm.Secret if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil { return nil, err } return &secret, nil } // ListSecretsOptions specify parameters to the ListSecrets function. // // See https://goo.gl/DwvNMd for more details. type ListSecretsOptions struct { Filters map[string][]string Context context.Context } // ListSecrets returns a slice of secrets matching the given criteria. // // See https://goo.gl/DwvNMd for more details. func (c *Client) ListSecrets(opts ListSecretsOptions) ([]swarm.Secret, error) { path := "/secrets?" + queryString(opts) resp, err := c.do(http.MethodGet, path, doOptions{context: opts.Context}) if err != nil { return nil, err } defer resp.Body.Close() var secrets []swarm.Secret if err := json.NewDecoder(resp.Body).Decode(&secrets); err != nil { return nil, err } return secrets, nil }