summaryrefslogtreecommitdiff
path: root/pkg/api
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2021-02-09 17:51:08 +0100
committerGitHub <noreply@github.com>2021-02-09 17:51:08 +0100
commitf98605e0e4f25c148b27cc617976357ff5b9d96e (patch)
tree6ffd63474853fcc7c2056964984e1fb88c3c0314 /pkg/api
parent9da4169e312bb822a0fbae8e18a0eb7c7eff6e64 (diff)
parent832a69b0bee6ec289521fbd59ddd480372493ee3 (diff)
downloadpodman-f98605e0e4f25c148b27cc617976357ff5b9d96e.tar.gz
podman-f98605e0e4f25c148b27cc617976357ff5b9d96e.tar.bz2
podman-f98605e0e4f25c148b27cc617976357ff5b9d96e.zip
Merge pull request #9125 from ashley-cui/secretswiring
Implement Secrets
Diffstat (limited to 'pkg/api')
-rw-r--r--pkg/api/handlers/compat/secrets.go121
-rw-r--r--pkg/api/handlers/libpod/secrets.go40
-rw-r--r--pkg/api/handlers/utils/errors.go8
-rw-r--r--pkg/api/server/register_secrets.go194
-rw-r--r--pkg/api/server/server.go1
-rw-r--r--pkg/api/tags.yaml4
6 files changed, 368 insertions, 0 deletions
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
new file mode 100644
index 000000000..ea2dfc707
--- /dev/null
+++ b/pkg/api/handlers/compat/secrets.go
@@ -0,0 +1,121 @@
+package compat
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "net/http"
+
+ "github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/infra/abi"
+ "github.com/gorilla/schema"
+ "github.com/pkg/errors"
+)
+
+func ListSecrets(w http.ResponseWriter, r *http.Request) {
+ var (
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ decoder = r.Context().Value("decoder").(*schema.Decoder)
+ )
+ query := struct {
+ Filters map[string][]string `schema:"filters"`
+ }{}
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+ if len(query.Filters) > 0 {
+ utils.Error(w, "filters not supported", http.StatusBadRequest, errors.New("bad parameter"))
+ }
+ ic := abi.ContainerEngine{Libpod: runtime}
+ reports, err := ic.SecretList(r.Context())
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, reports)
+}
+
+func InspectSecret(w http.ResponseWriter, r *http.Request) {
+ var (
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ )
+ name := utils.GetName(r)
+ names := []string{name}
+ ic := abi.ContainerEngine{Libpod: runtime}
+ reports, errs, err := ic.SecretInspect(r.Context(), names)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ if len(errs) > 0 {
+ utils.SecretNotFound(w, name, errs[0])
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, reports[0])
+
+}
+
+func RemoveSecret(w http.ResponseWriter, r *http.Request) {
+ var (
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ )
+
+ opts := entities.SecretRmOptions{}
+ name := utils.GetName(r)
+ ic := abi.ContainerEngine{Libpod: runtime}
+ reports, err := ic.SecretRm(r.Context(), []string{name}, opts)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ if reports[0].Err != nil {
+ utils.SecretNotFound(w, name, reports[0].Err)
+ return
+ }
+ utils.WriteResponse(w, http.StatusNoContent, nil)
+}
+
+func CreateSecret(w http.ResponseWriter, r *http.Request) {
+ var (
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ )
+ opts := entities.SecretCreateOptions{}
+ createParams := struct {
+ *entities.SecretCreateRequest
+ Labels map[string]string `schema:"labels"`
+ }{}
+
+ if err := json.NewDecoder(r.Body).Decode(&createParams); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ return
+ }
+ if len(createParams.Labels) > 0 {
+ utils.Error(w, "labels not supported", http.StatusBadRequest, errors.New("bad parameter"))
+ }
+
+ decoded, _ := base64.StdEncoding.DecodeString(createParams.Data)
+ reader := bytes.NewReader(decoded)
+ opts.Driver = createParams.Driver.Name
+
+ ic := abi.ContainerEngine{Libpod: runtime}
+ report, err := ic.SecretCreate(r.Context(), createParams.Name, reader, opts)
+ if err != nil {
+ if errors.Cause(err).Error() == "secret name in use" {
+ utils.Error(w, "name conflicts with an existing object", http.StatusConflict, err)
+ return
+ }
+ utils.InternalServerError(w, err)
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, report)
+}
+
+func UpdateSecret(w http.ResponseWriter, r *http.Request) {
+ utils.Error(w, fmt.Sprintf("unsupported endpoint: %v", r.Method), http.StatusNotImplemented, errors.New("update is not supported"))
+}
diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go
new file mode 100644
index 000000000..447a5d021
--- /dev/null
+++ b/pkg/api/handlers/libpod/secrets.go
@@ -0,0 +1,40 @@
+package libpod
+
+import (
+ "net/http"
+
+ "github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/infra/abi"
+ "github.com/gorilla/schema"
+ "github.com/pkg/errors"
+)
+
+func CreateSecret(w http.ResponseWriter, r *http.Request) {
+ var (
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ decoder = r.Context().Value("decoder").(*schema.Decoder)
+ )
+ query := struct {
+ Name string `schema:"name"`
+ Driver string `schema:"driver"`
+ }{
+ // override any golang type defaults
+ }
+ opts := entities.SecretCreateOptions{}
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+ opts.Driver = query.Driver
+
+ ic := abi.ContainerEngine{Libpod: runtime}
+ report, err := ic.SecretCreate(r.Context(), query.Name, r.Body, opts)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, report)
+}
diff --git a/pkg/api/handlers/utils/errors.go b/pkg/api/handlers/utils/errors.go
index e2c287c45..c8785fb89 100644
--- a/pkg/api/handlers/utils/errors.go
+++ b/pkg/api/handlers/utils/errors.go
@@ -80,6 +80,14 @@ func SessionNotFound(w http.ResponseWriter, name string, err error) {
Error(w, msg, http.StatusNotFound, err)
}
+func SecretNotFound(w http.ResponseWriter, nameOrID string, err error) {
+ if errors.Cause(err).Error() != "no such secret" {
+ InternalServerError(w, err)
+ }
+ msg := fmt.Sprintf("No such secret: %s", nameOrID)
+ Error(w, msg, http.StatusNotFound, err)
+}
+
func ContainerNotRunning(w http.ResponseWriter, containerID string, err error) {
msg := fmt.Sprintf("Container %s is not running", containerID)
Error(w, msg, http.StatusConflict, err)
diff --git a/pkg/api/server/register_secrets.go b/pkg/api/server/register_secrets.go
new file mode 100644
index 000000000..95abf83e8
--- /dev/null
+++ b/pkg/api/server/register_secrets.go
@@ -0,0 +1,194 @@
+package server
+
+import (
+ "net/http"
+
+ "github.com/containers/podman/v2/pkg/api/handlers/compat"
+ "github.com/containers/podman/v2/pkg/api/handlers/libpod"
+ "github.com/gorilla/mux"
+)
+
+func (s *APIServer) registerSecretHandlers(r *mux.Router) error {
+ // swagger:operation POST /libpod/secrets/create libpod libpodCreateSecret
+ // ---
+ // tags:
+ // - secrets
+ // summary: Create a secret
+ // parameters:
+ // - in: query
+ // name: name
+ // type: string
+ // description: User-defined name of the secret.
+ // required: true
+ // - in: query
+ // name: driver
+ // type: string
+ // description: Secret driver
+ // default: "file"
+ // - in: body
+ // name: request
+ // description: Secret
+ // schema:
+ // type: string
+ // produces:
+ // - application/json
+ // responses:
+ // '201':
+ // $ref: "#/responses/SecretCreateResponse"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/secrets/create"), s.APIHandler(libpod.CreateSecret)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/secrets/json libpod libpodListSecret
+ // ---
+ // tags:
+ // - secrets
+ // summary: List secrets
+ // description: Returns a list of secrets
+ // produces:
+ // - application/json
+ // parameters:
+ // responses:
+ // '200':
+ // "$ref": "#/responses/SecretListResponse"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/secrets/json"), s.APIHandler(compat.ListSecrets)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/secrets/{name}/json libpod libpodInspectSecret
+ // ---
+ // tags:
+ // - secrets
+ // summary: Inspect secret
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the secret
+ // produces:
+ // - application/json
+ // responses:
+ // '200':
+ // "$ref": "#/responses/SecretInspectResponse"
+ // '404':
+ // "$ref": "#/responses/NoSuchSecret"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/secrets/{name}/json"), s.APIHandler(compat.InspectSecret)).Methods(http.MethodGet)
+ // swagger:operation DELETE /libpod/secrets/{name} libpod libpodRemoveSecret
+ // ---
+ // tags:
+ // - secrets
+ // summary: Remove secret
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the secret
+ // - in: query
+ // name: all
+ // type: boolean
+ // description: Remove all secrets
+ // default: false
+ // produces:
+ // - application/json
+ // responses:
+ // '204':
+ // description: no error
+ // '404':
+ // "$ref": "#/responses/NoSuchSecret"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/secrets/{name}"), s.APIHandler(compat.RemoveSecret)).Methods(http.MethodDelete)
+
+ /*
+ * Docker compatibility endpoints
+ */
+ // swagger:operation GET /secrets compat ListSecret
+ // ---
+ // tags:
+ // - secrets (compat)
+ // summary: List secrets
+ // description: Returns a list of secrets
+ // produces:
+ // - application/json
+ // parameters:
+ // responses:
+ // '200':
+ // "$ref": "#/responses/SecretListResponse"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/secrets"), s.APIHandler(compat.ListSecrets)).Methods(http.MethodGet)
+ r.Handle("/secrets", s.APIHandler(compat.ListSecrets)).Methods(http.MethodGet)
+ // swagger:operation POST /secrets/create compat CreateSecret
+ // ---
+ // tags:
+ // - secrets (compat)
+ // summary: Create a secret
+ // parameters:
+ // - in: body
+ // name: create
+ // description: |
+ // attributes for creating a secret
+ // schema:
+ // $ref: "#/definitions/SecretCreate"
+ // produces:
+ // - application/json
+ // responses:
+ // '201':
+ // $ref: "#/responses/SecretCreateResponse"
+ // '409':
+ // "$ref": "#/responses/SecretInUse"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/secrets/create"), s.APIHandler(compat.CreateSecret)).Methods(http.MethodPost)
+ r.Handle("/secrets/create", s.APIHandler(compat.CreateSecret)).Methods(http.MethodPost)
+ // swagger:operation GET /secrets/{name} compat InspectSecret
+ // ---
+ // tags:
+ // - secrets (compat)
+ // summary: Inspect secret
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the secret
+ // produces:
+ // - application/json
+ // responses:
+ // '200':
+ // "$ref": "#/responses/SecretInspectResponse"
+ // '404':
+ // "$ref": "#/responses/NoSuchSecret"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/secrets/{name}"), s.APIHandler(compat.InspectSecret)).Methods(http.MethodGet)
+ r.Handle("/secrets/{name}", s.APIHandler(compat.InspectSecret)).Methods(http.MethodGet)
+ // swagger:operation DELETE /secrets/{name} compat RemoveSecret
+ // ---
+ // tags:
+ // - secrets (compat)
+ // summary: Remove secret
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the secret
+ // produces:
+ // - application/json
+ // responses:
+ // '204':
+ // description: no error
+ // '404':
+ // "$ref": "#/responses/NoSuchSecret"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/secrets/{name}"), s.APIHandler(compat.RemoveSecret)).Methods(http.MethodDelete)
+ r.Handle("/secret/{name}", s.APIHandler(compat.RemoveSecret)).Methods(http.MethodDelete)
+
+ r.Handle(VersionedPath("/secrets/{name}/update"), s.APIHandler(compat.UpdateSecret)).Methods(http.MethodPost)
+ r.Handle("/secrets/{name}/update", s.APIHandler(compat.UpdateSecret)).Methods(http.MethodPost)
+ return nil
+}
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index d612041f6..6926eda62 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -124,6 +124,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
server.registerPlayHandlers,
server.registerPluginsHandlers,
server.registerPodsHandlers,
+ server.registerSecretHandlers,
server.RegisterSwaggerHandlers,
server.registerSwarmHandlers,
server.registerSystemHandlers,
diff --git a/pkg/api/tags.yaml b/pkg/api/tags.yaml
index 0cfb3f440..bb56098eb 100644
--- a/pkg/api/tags.yaml
+++ b/pkg/api/tags.yaml
@@ -13,6 +13,8 @@ tags:
description: Actions related to pods
- name: volumes
description: Actions related to volumes
+ - name: secrets
+ description: Actions related to secrets
- name: system
description: Actions related to Podman engine
- name: containers (compat)
@@ -25,5 +27,7 @@ tags:
description: Actions related to compatibility networks
- name: volumes (compat)
description: Actions related to volumes for the compatibility endpoints
+ - name: secrets (compat)
+ description: Actions related to secrets for the compatibility endpoints
- name: system (compat)
description: Actions related to Podman and compatibility engines