mirror of
https://github.com/containers/podman.git
synced 2025-05-17 15:18:43 +08:00
Merge pull request #18019 from ygalblum/add-secret-exists
Add support for secret exists
This commit is contained in:
38
cmd/podman/secrets/exists.go
Normal file
38
cmd/podman/secrets/exists.go
Normal file
@ -0,0 +1,38 @@
|
||||
package secrets
|
||||
|
||||
import (
|
||||
"github.com/containers/podman/v4/cmd/podman/common"
|
||||
"github.com/containers/podman/v4/cmd/podman/registry"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
existsCmd = &cobra.Command{
|
||||
Use: "exists SECRET",
|
||||
Short: "Check if a secret exists in local storage",
|
||||
Long: `If the named secret exists in local storage, podman secret exists exits with 0, otherwise the exit code will be 1.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: exists,
|
||||
ValidArgsFunction: common.AutocompleteSecrets,
|
||||
Example: `podman secret exists ID
|
||||
podman secret exists SECRET || podman secret create SECRET <secret source>`,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Command: existsCmd,
|
||||
Parent: secretCmd,
|
||||
})
|
||||
}
|
||||
|
||||
func exists(cmd *cobra.Command, args []string) error {
|
||||
found, err := registry.ContainerEngine().SecretExists(registry.GetContext(), args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !found.Value {
|
||||
registry.SetExitCode(1)
|
||||
}
|
||||
return nil
|
||||
}
|
43
docs/source/markdown/podman-secret-exists.1.md
Normal file
43
docs/source/markdown/podman-secret-exists.1.md
Normal file
@ -0,0 +1,43 @@
|
||||
% podman-secret-exists 1
|
||||
|
||||
## NAME
|
||||
podman\-secret\-exists - Check if the given secret exists
|
||||
|
||||
## SYNOPSIS
|
||||
**podman secret exists** *secret*
|
||||
|
||||
## DESCRIPTION
|
||||
**podman secret exists** checks if a secret exists. Podman will return an exit code
|
||||
of `0` when the secret is found. A `1` will be returned otherwise. An exit code of
|
||||
`125` indicates there was another issue.
|
||||
|
||||
|
||||
## OPTIONS
|
||||
|
||||
#### **--help**, **-h**
|
||||
|
||||
Print usage statement
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
Check if a secret called `mysecret` exists (the secret does actually exist).
|
||||
```
|
||||
$ podman secret exists mysecret
|
||||
$ echo $?
|
||||
0
|
||||
$
|
||||
```
|
||||
|
||||
Check if a secret called `mypassword` exists (the secret does not actually exist).
|
||||
```
|
||||
$ podman secret exists mypassword
|
||||
$ echo $?
|
||||
1
|
||||
$
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
**[podman(1)](podman.1.md)**, **[podman-secret(1)](podman-secret.1.md)**
|
||||
|
||||
## HISTORY
|
||||
April 2023, Originally compiled by Ygal Blum `<ygal.blum@gmail.com>`
|
@ -14,6 +14,7 @@ podman secret is a set of subcommands that manage secrets.
|
||||
| Command | Man Page | Description |
|
||||
| ------- | ------------------------------------------------------ | ------------------------------------------------------ |
|
||||
| create | [podman-secret-create(1)](podman-secret-create.1.md) | Create a new secret |
|
||||
| exists | [podman-secret-exists(1)](podman-secret-exists.1.md) | Check if the given secret exists |
|
||||
| inspect | [podman-secret-inspect(1)](podman-secret-inspect.1.md) | Display detailed information on one or more secrets |
|
||||
| ls | [podman-secret-ls(1)](podman-secret-ls.1.md) | List all available secrets |
|
||||
| rm | [podman-secret-rm(1)](podman-secret-rm.1.md) | Remove one or more secrets |
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/containers/common/pkg/secrets"
|
||||
"github.com/containers/podman/v4/libpod"
|
||||
"github.com/containers/podman/v4/pkg/api/handlers/utils"
|
||||
api "github.com/containers/podman/v4/pkg/api/types"
|
||||
@ -44,3 +45,20 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
}
|
||||
|
||||
func SecretExists(w http.ResponseWriter, r *http.Request) {
|
||||
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
|
||||
name := utils.GetName(r)
|
||||
ic := abi.ContainerEngine{Libpod: runtime}
|
||||
|
||||
report, err := ic.SecretExists(r.Context(), name)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
if !report.Value {
|
||||
utils.SecretNotFound(w, name, secrets.ErrNoSuchSecret)
|
||||
return
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusNoContent, "")
|
||||
}
|
||||
|
@ -89,6 +89,27 @@ func (s *APIServer) registerSecretHandlers(r *mux.Router) error {
|
||||
// '500':
|
||||
// "$ref": "#/responses/internalError"
|
||||
r.Handle(VersionedPath("/libpod/secrets/{name}/json"), s.APIHandler(compat.InspectSecret)).Methods(http.MethodGet)
|
||||
// swagger:operation GET /libpod/secrets/{name}/exists libpod SecretExistsLibpod
|
||||
// ---
|
||||
// tags:
|
||||
// - secrets
|
||||
// summary: Secret exists
|
||||
// parameters:
|
||||
// - in: path
|
||||
// name: name
|
||||
// type: string
|
||||
// required: true
|
||||
// description: the name or ID of the secret
|
||||
// produces:
|
||||
// - application/json
|
||||
// responses:
|
||||
// 204:
|
||||
// description: secret exists
|
||||
// 404:
|
||||
// $ref: '#/responses/NoSuchSecret'
|
||||
// '500':
|
||||
// "$ref": "#/responses/internalError"
|
||||
r.Handle(VersionedPath("/libpod/secrets/{name}/exists"), s.APIHandler(libpod.SecretExists)).Methods(http.MethodGet)
|
||||
// swagger:operation DELETE /libpod/secrets/{name} libpod SecretDeleteLibpod
|
||||
// ---
|
||||
// tags:
|
||||
|
@ -88,3 +88,17 @@ func Create(ctx context.Context, reader io.Reader, options *CreateOptions) (*ent
|
||||
|
||||
return create, response.Process(&create)
|
||||
}
|
||||
|
||||
func Exists(ctx context.Context, nameOrID string) (bool, error) {
|
||||
conn, err := bindings.GetClient(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/secrets/%s/exists", nil, nil, nameOrID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
return response.IsSuccess(), nil
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ type ContainerEngine interface { //nolint:interfacebloat
|
||||
SecretInspect(ctx context.Context, nameOrIDs []string) ([]*SecretInfoReport, []error, error)
|
||||
SecretList(ctx context.Context, opts SecretListRequest) ([]*SecretInfoReport, error)
|
||||
SecretRm(ctx context.Context, nameOrID []string, opts SecretRmOptions) ([]*SecretRmReport, error)
|
||||
SecretExists(ctx context.Context, nameOrID string) (*BoolReport, error)
|
||||
Shutdown(ctx context.Context)
|
||||
SystemDf(ctx context.Context, options SystemDfOptions) (*SystemDfReport, error)
|
||||
Unshare(ctx context.Context, args []string, options SystemUnshareOptions) error
|
||||
|
@ -2,6 +2,7 @@ package abi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
@ -165,3 +166,17 @@ func (ic *ContainerEngine) SecretRm(ctx context.Context, nameOrIDs []string, opt
|
||||
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) SecretExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
|
||||
manager, err := ic.Libpod.SecretsManager()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
secret, err := manager.Lookup(nameOrID)
|
||||
if err != nil && !errors.Is(err, secrets.ErrNoSuchSecret) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &entities.BoolReport{Value: secret != nil}, nil
|
||||
}
|
||||
|
@ -87,3 +87,11 @@ func (ic *ContainerEngine) SecretRm(ctx context.Context, nameOrIDs []string, opt
|
||||
}
|
||||
return allRm, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) SecretExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
|
||||
exists, err := secrets.Exists(ic.ClientCtx, nameOrID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &entities.BoolReport{Value: exists}, nil
|
||||
}
|
||||
|
@ -18,6 +18,12 @@ t GET secrets/mysecret 200 \
|
||||
# secret inspect non-existent secret
|
||||
t GET secrets/bogus 404
|
||||
|
||||
# Check exists with existing secret
|
||||
t GET libpod/secrets/mysecret/exists 204
|
||||
|
||||
# Check exists for non-existing secret
|
||||
t GET libpod/secrets/bogus/exists 404
|
||||
|
||||
# secret list
|
||||
t GET secrets 200 \
|
||||
length=1 \
|
||||
|
@ -372,4 +372,33 @@ var _ = Describe("Podman secret", func() {
|
||||
Expect(inspect.OutputToString()).To(Equal("map[]"))
|
||||
|
||||
})
|
||||
|
||||
It("podman secret exists should return true if secret exists", func() {
|
||||
secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
|
||||
err := os.WriteFile(secretFilePath, []byte("mysecret"), 0755)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
secretName := "does_exist"
|
||||
|
||||
session := podmanTest.Podman([]string{"secret", "create", secretName, secretFilePath})
|
||||
session.WaitWithDefaultTimeout()
|
||||
secretID := session.OutputToString()
|
||||
Expect(session).Should(Exit(0))
|
||||
|
||||
exists := podmanTest.Podman([]string{"secret", "exists", secretName})
|
||||
exists.WaitWithDefaultTimeout()
|
||||
Expect(exists).Should(Exit(0))
|
||||
|
||||
exists = podmanTest.Podman([]string{"secret", "exists", secretID})
|
||||
exists.WaitWithDefaultTimeout()
|
||||
Expect(exists).Should(Exit(0))
|
||||
})
|
||||
|
||||
It("podman secret exists should return false if secret does not exist", func() {
|
||||
secretName := "does_not_exist"
|
||||
|
||||
exists := podmanTest.Podman([]string{"secret", "exists", secretName})
|
||||
exists.WaitWithDefaultTimeout()
|
||||
Expect(exists).Should(Exit(1))
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user