mirror of https://github.com/containers/podman.git
Merge pull request #12586 from jmguzik/secret-cmd
Add secret list --filter to cli
This commit is contained in:
commit
a0894b5ecd
|
@ -209,7 +209,7 @@ func getImages(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellComp
|
||||||
return suggestions, cobra.ShellCompDirectiveNoFileComp
|
return suggestions, cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSecrets(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func getSecrets(cmd *cobra.Command, toComplete string, cType completeType) ([]string, cobra.ShellCompDirective) {
|
||||||
suggestions := []string{}
|
suggestions := []string{}
|
||||||
|
|
||||||
engine, err := setupContainerEngine(cmd)
|
engine, err := setupContainerEngine(cmd)
|
||||||
|
@ -224,7 +224,13 @@ func getSecrets(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCom
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range secrets {
|
for _, s := range secrets {
|
||||||
if strings.HasPrefix(s.Spec.Name, toComplete) {
|
// works the same as in getNetworks
|
||||||
|
if ((len(toComplete) > 1 && cType == completeDefault) ||
|
||||||
|
cType == completeIDs) && strings.HasPrefix(s.ID, toComplete) {
|
||||||
|
suggestions = append(suggestions, s.ID[0:12])
|
||||||
|
}
|
||||||
|
// include name in suggestions
|
||||||
|
if cType != completeIDs && strings.HasPrefix(s.Spec.Name, toComplete) {
|
||||||
suggestions = append(suggestions, s.Spec.Name)
|
suggestions = append(suggestions, s.Spec.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,7 +476,7 @@ func AutocompleteSecrets(cmd *cobra.Command, args []string, toComplete string) (
|
||||||
if !validCurrentCmdLine(cmd, args, toComplete) {
|
if !validCurrentCmdLine(cmd, args, toComplete) {
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
return getSecrets(cmd, toComplete)
|
return getSecrets(cmd, toComplete, completeDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AutocompleteSecretCreate(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func AutocompleteSecretCreate(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
@ -1283,6 +1289,15 @@ func AutocompleteVolumeFilters(cmd *cobra.Command, args []string, toComplete str
|
||||||
return completeKeyValues(toComplete, kv)
|
return completeKeyValues(toComplete, kv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AutocompleteSecretFilters - Autocomplete secret ls --filter options.
|
||||||
|
func AutocompleteSecretFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
kv := keyValueCompletion{
|
||||||
|
"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getSecrets(cmd, s, completeNames) },
|
||||||
|
"id=": func(s string) ([]string, cobra.ShellCompDirective) { return getSecrets(cmd, s, completeIDs) },
|
||||||
|
}
|
||||||
|
return completeKeyValues(toComplete, kv)
|
||||||
|
}
|
||||||
|
|
||||||
// AutocompleteCheckpointCompressType - Autocomplete checkpoint compress type options.
|
// AutocompleteCheckpointCompressType - Autocomplete checkpoint compress type options.
|
||||||
// -> "gzip", "none", "zstd"
|
// -> "gzip", "none", "zstd"
|
||||||
func AutocompleteCheckpointCompressType(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func AutocompleteCheckpointCompressType(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/containers/common/pkg/completion"
|
"github.com/containers/common/pkg/completion"
|
||||||
"github.com/containers/common/pkg/report"
|
"github.com/containers/common/pkg/report"
|
||||||
"github.com/containers/podman/v3/cmd/podman/common"
|
"github.com/containers/podman/v3/cmd/podman/common"
|
||||||
|
"github.com/containers/podman/v3/cmd/podman/parse"
|
||||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||||
|
@ -32,6 +33,7 @@ var (
|
||||||
type listFlagType struct {
|
type listFlagType struct {
|
||||||
format string
|
format string
|
||||||
noHeading bool
|
noHeading bool
|
||||||
|
filter []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -44,14 +46,26 @@ func init() {
|
||||||
formatFlagName := "format"
|
formatFlagName := "format"
|
||||||
flags.StringVar(&listFlag.format, formatFlagName, "{{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}\t\n", "Format volume output using Go template")
|
flags.StringVar(&listFlag.format, formatFlagName, "{{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}\t\n", "Format volume output using Go template")
|
||||||
_ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.SecretInfoReport{}))
|
_ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.SecretInfoReport{}))
|
||||||
|
filterFlagName := "filter"
|
||||||
|
flags.StringSliceVarP(&listFlag.filter, filterFlagName, "f", []string{}, "Filter secret output")
|
||||||
|
_ = lsCmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteSecretFilters)
|
||||||
flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers")
|
flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers")
|
||||||
}
|
}
|
||||||
|
|
||||||
func ls(cmd *cobra.Command, args []string) error {
|
func ls(cmd *cobra.Command, args []string) error {
|
||||||
responses, err := registry.ContainerEngine().SecretList(context.Background(), entities.SecretListRequest{})
|
var err error
|
||||||
|
lsOpts := entities.SecretListRequest{}
|
||||||
|
|
||||||
|
lsOpts.Filters, err = parse.FilterArgumentsIntoFilters(listFlag.filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
responses, err := registry.ContainerEngine().SecretList(context.Background(), lsOpts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
listed := make([]*entities.SecretListReport, 0, len(responses))
|
listed := make([]*entities.SecretListReport, 0, len(responses))
|
||||||
for _, response := range responses {
|
for _, response := range responses {
|
||||||
listed = append(listed, &entities.SecretListReport{
|
listed = append(listed, &entities.SecretListReport{
|
||||||
|
|
|
@ -4,11 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containers/common/pkg/completion"
|
"github.com/containers/common/pkg/completion"
|
||||||
"github.com/containers/common/pkg/report"
|
"github.com/containers/common/pkg/report"
|
||||||
"github.com/containers/podman/v3/cmd/podman/common"
|
"github.com/containers/podman/v3/cmd/podman/common"
|
||||||
|
"github.com/containers/podman/v3/cmd/podman/parse"
|
||||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v3/libpod/define"
|
"github.com/containers/podman/v3/libpod/define"
|
||||||
|
@ -64,19 +64,18 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func list(cmd *cobra.Command, args []string) error {
|
func list(cmd *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
if cliOpts.Quiet && cmd.Flag("format").Changed {
|
if cliOpts.Quiet && cmd.Flag("format").Changed {
|
||||||
return errors.New("quiet and format flags cannot be used together")
|
return errors.New("quiet and format flags cannot be used together")
|
||||||
}
|
}
|
||||||
if len(cliOpts.Filter) > 0 {
|
if len(cliOpts.Filter) > 0 {
|
||||||
lsOpts.Filter = make(map[string][]string)
|
lsOpts.Filter = make(map[string][]string)
|
||||||
}
|
}
|
||||||
for _, f := range cliOpts.Filter {
|
lsOpts.Filter, err = parse.FilterArgumentsIntoFilters(cliOpts.Filter)
|
||||||
filterSplit := strings.SplitN(f, "=", 2)
|
if err != nil {
|
||||||
if len(filterSplit) < 2 {
|
return err
|
||||||
return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
|
|
||||||
}
|
|
||||||
lsOpts.Filter[filterSplit[0]] = append(lsOpts.Filter[filterSplit[0]], filterSplit[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
responses, err := registry.ContainerEngine().VolumeList(context.Background(), lsOpts)
|
responses, err := registry.ContainerEngine().VolumeList(context.Background(), lsOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -58,6 +58,9 @@ func prune(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pruneOptions.Filters, err = parse.FilterArgumentsIntoFilters(filter)
|
pruneOptions.Filters, err = parse.FilterArgumentsIntoFilters(filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if !force {
|
if !force {
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
fmt.Println("WARNING! This will remove all volumes not used by at least one container. The following volumes will be removed:")
|
fmt.Println("WARNING! This will remove all volumes not used by at least one container. The following volumes will be removed:")
|
||||||
|
|
|
@ -20,11 +20,24 @@ Format secret output using Go template.
|
||||||
|
|
||||||
Omit the table headings from the listing of secrets. .
|
Omit the table headings from the listing of secrets. .
|
||||||
|
|
||||||
|
#### **--filter**, **-f**=*filter=value*
|
||||||
|
|
||||||
|
Filter output based on conditions given.
|
||||||
|
Multiple filters can be given with multiple uses of the --filter option.
|
||||||
|
|
||||||
|
Valid filters are listed below:
|
||||||
|
|
||||||
|
| **Filter** | **Description** |
|
||||||
|
| ---------- | ----------------------------------------------------------------- |
|
||||||
|
| name | [Name] Secret name (accepts regex) |
|
||||||
|
| id | [ID] Full or partial secret ID |
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
$ podman secret ls
|
$ podman secret ls
|
||||||
$ podman secret ls --format "{{.Name}}"
|
$ podman secret ls --format "{{.Name}}"
|
||||||
|
$ podman secret ls --filter name=confidential
|
||||||
```
|
```
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -145,6 +146,54 @@ var _ = Describe("Podman secret", func() {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman secret ls with filters", func() {
|
||||||
|
secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
|
||||||
|
err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
secret1 := "Secret1"
|
||||||
|
secret2 := "Secret2"
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"secret", "create", secret1, secretFilePath})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
secrID1 := session.OutputToString()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"secret", "create", secret2, secretFilePath})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
secrID2 := session.OutputToString()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"secret", "create", "Secret3", secretFilePath})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
list := podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s", secret1)})
|
||||||
|
list.WaitWithDefaultTimeout()
|
||||||
|
Expect(list).Should(Exit(0))
|
||||||
|
Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secret1))
|
||||||
|
|
||||||
|
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s", secret2)})
|
||||||
|
list.WaitWithDefaultTimeout()
|
||||||
|
Expect(list).Should(Exit(0))
|
||||||
|
Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secret2))
|
||||||
|
|
||||||
|
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("id=%s", secrID1)})
|
||||||
|
list.WaitWithDefaultTimeout()
|
||||||
|
Expect(list).Should(Exit(0))
|
||||||
|
Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secrID1))
|
||||||
|
|
||||||
|
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("id=%s", secrID2)})
|
||||||
|
list.WaitWithDefaultTimeout()
|
||||||
|
Expect(list).Should(Exit(0))
|
||||||
|
Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secrID2))
|
||||||
|
|
||||||
|
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s,name=%s", secret1, secret2)})
|
||||||
|
list.WaitWithDefaultTimeout()
|
||||||
|
Expect(list).Should(Exit(0))
|
||||||
|
Expect(list.OutputToStringArray()).To(HaveLen(3), ContainSubstring(secret1), ContainSubstring(secret2))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman secret ls with Go template", func() {
|
It("podman secret ls with Go template", func() {
|
||||||
secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
|
secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
|
||||||
err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755)
|
err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755)
|
||||||
|
|
Loading…
Reference in New Issue