Skip to content

Commit

Permalink
Merge pull request #11431 from jmguzik/secrets-ls-filters
Browse files Browse the repository at this point in the history
Add filtering functionality to http api secrets list
  • Loading branch information
openshift-merge-robot authored Sep 7, 2021
2 parents fbae579 + d346e6e commit 536f23c
Show file tree
Hide file tree
Showing 13 changed files with 127 additions and 35 deletions.
2 changes: 1 addition & 1 deletion cmd/podman/common/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func getSecrets(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCom
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}
secrets, err := engine.SecretList(registry.GetContext())
secrets, err := engine.SecretList(registry.GetContext(), entities.SecretListRequest{})
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
2 changes: 1 addition & 1 deletion cmd/podman/secrets/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func init() {
}

func ls(cmd *cobra.Command, args []string) error {
responses, err := registry.ContainerEngine().SecretList(context.Background())
responses, err := registry.ContainerEngine().SecretList(context.Background(), entities.SecretListRequest{})
if err != nil {
return err
}
Expand Down
22 changes: 8 additions & 14 deletions pkg/api/handlers/compat/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,25 @@ import (
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/gorilla/schema"
"github.com/containers/podman/v3/pkg/util"
"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,
filtersMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
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.Wrapf(errors.New("bad parameter"), "filters not supported"))
return
}
ic := abi.ContainerEngine{Libpod: runtime}
reports, err := ic.SecretList(r.Context())
listOptions := entities.SecretListRequest{
Filters: *filtersMap,
}
reports, err := ic.SecretList(r.Context(), listOptions)
if err != nil {
utils.InternalServerError(w, err)
return
Expand Down
16 changes: 16 additions & 0 deletions pkg/api/server/register_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ func (s *APIServer) registerSecretHandlers(r *mux.Router) error {
// - secrets
// summary: List secrets
// description: Returns a list of secrets
// parameters:
// - in: query
// name: filters
// type: string
// description: |
// JSON encoded value of the filters (a `map[string][]string`) to process on the secrets list. Currently available filters:
// - `name=[name]` Matches secrets name (accepts regex).
// - `id=[id]` Matches for full or partial ID.
// produces:
// - application/json
// parameters:
Expand Down Expand Up @@ -110,6 +118,14 @@ func (s *APIServer) registerSecretHandlers(r *mux.Router) error {
// - secrets (compat)
// summary: List secrets
// description: Returns a list of secrets
// parameters:
// - in: query
// name: filters
// type: string
// description: |
// JSON encoded value of the filters (a `map[string][]string`) to process on the secrets list. Currently available filters:
// - `name=[name]` Matches secrets name (accepts regex).
// - `id=[id]` Matches for full or partial ID.
// produces:
// - application/json
// parameters:
Expand Down
6 changes: 5 additions & 1 deletion pkg/bindings/secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ func List(ctx context.Context, options *ListOptions) ([]*entities.SecretInfoRepo
if err != nil {
return nil, err
}
response, err := conn.DoRequest(nil, http.MethodGet, "/secrets/json", nil, nil)
params, err := options.ToParams()
if err != nil {
return nil, err
}
response, err := conn.DoRequest(nil, http.MethodGet, "/secrets/json", params, nil)
if err != nil {
return secrs, err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/bindings/secrets/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package secrets
//go:generate go run ../generator/generator.go ListOptions
// ListOptions are optional options for inspecting secrets
type ListOptions struct {
Filters map[string][]string
}

//go:generate go run ../generator/generator.go InspectOptions
Expand Down
16 changes: 16 additions & 0 deletions pkg/bindings/secrets/types_list_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,19 @@ func (o *ListOptions) Changed(fieldName string) bool {
func (o *ListOptions) ToParams() (url.Values, error) {
return util.ToParams(o)
}

// WithFilters
func (o *ListOptions) WithFilters(value map[string][]string) *ListOptions {
v := value
o.Filters = v
return o
}

// GetFilters
func (o *ListOptions) GetFilters() map[string][]string {
var filters map[string][]string
if o.Filters == nil {
return filters
}
return o.Filters
}
2 changes: 1 addition & 1 deletion pkg/domain/entities/engine_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ type ContainerEngine interface {
SetupRootless(ctx context.Context, noMoveProcess bool) error
SecretCreate(ctx context.Context, name string, reader io.Reader, options SecretCreateOptions) (*SecretCreateReport, error)
SecretInspect(ctx context.Context, nameOrIDs []string) ([]*SecretInfoReport, []error, error)
SecretList(ctx context.Context) ([]*SecretInfoReport, error)
SecretList(ctx context.Context, opts SecretListRequest) ([]*SecretInfoReport, error)
SecretRm(ctx context.Context, nameOrID []string, opts SecretRmOptions) ([]*SecretRmReport, error)
Shutdown(ctx context.Context)
SystemDf(ctx context.Context, options SystemDfOptions) (*SystemDfReport, error)
Expand Down
2 changes: 1 addition & 1 deletion pkg/domain/entities/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type SecretCreateOptions struct {
}

type SecretListRequest struct {
Filters map[string]string
Filters map[string][]string
}

type SecretListReport struct {
Expand Down
31 changes: 19 additions & 12 deletions pkg/domain/infra/abi/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"path/filepath"

"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/utils"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -84,7 +85,7 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string
return reports, errs, nil
}

func (ic *ContainerEngine) SecretList(ctx context.Context) ([]*entities.SecretInfoReport, error) {
func (ic *ContainerEngine) SecretList(ctx context.Context, opts entities.SecretListRequest) ([]*entities.SecretInfoReport, error) {
manager, err := ic.Libpod.SecretsManager()
if err != nil {
return nil, err
Expand All @@ -95,19 +96,25 @@ func (ic *ContainerEngine) SecretList(ctx context.Context) ([]*entities.SecretIn
}
report := make([]*entities.SecretInfoReport, 0, len(secretList))
for _, secret := range secretList {
reportItem := entities.SecretInfoReport{
ID: secret.ID,
CreatedAt: secret.CreatedAt,
UpdatedAt: secret.CreatedAt,
Spec: entities.SecretSpec{
Name: secret.Name,
Driver: entities.SecretDriverSpec{
Name: secret.Driver,
Options: secret.DriverOptions,
result, err := utils.IfPassesSecretsFilter(secret, opts.Filters)
if err != nil {
return nil, err
}
if result {
reportItem := entities.SecretInfoReport{
ID: secret.ID,
CreatedAt: secret.CreatedAt,
UpdatedAt: secret.CreatedAt,
Spec: entities.SecretSpec{
Name: secret.Name,
Driver: entities.SecretDriverSpec{
Name: secret.Driver,
Options: secret.DriverOptions,
},
},
},
}
report = append(report, &reportItem)
}
report = append(report, &reportItem)
}
return report, nil
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/domain/infra/tunnel/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string
return allInspect, errs, nil
}

func (ic *ContainerEngine) SecretList(ctx context.Context) ([]*entities.SecretInfoReport, error) {
secrs, _ := secrets.List(ic.ClientCtx, nil)
func (ic *ContainerEngine) SecretList(ctx context.Context, opts entities.SecretListRequest) ([]*entities.SecretInfoReport, error) {
options := new(secrets.ListOptions).WithFilters(opts.Filters)
secrs, _ := secrets.List(ic.ClientCtx, options)
return secrs, nil
}

Expand Down
24 changes: 24 additions & 0 deletions pkg/domain/utils/secrets_filters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package utils

import (
"strings"

"github.com/containers/common/pkg/secrets"
"github.com/containers/podman/v3/pkg/util"
"github.com/pkg/errors"
)

func IfPassesSecretsFilter(s secrets.Secret, filters map[string][]string) (bool, error) {
result := true
for key, filterValues := range filters {
switch strings.ToLower(key) {
case "name":
result = util.StringMatchRegexSlice(s.Name, filterValues)
case "id":
result = util.StringMatchRegexSlice(s.ID, filterValues)
default:
return false, errors.Errorf("invalid filter %q", key)
}
}
return result, nil
}
33 changes: 31 additions & 2 deletions test/apiv2/50-secrets.at
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,37 @@ t GET secrets 200 \
.[0].Spec.Name=mysecret \
.[0].Version.Index=1

# secret list unsupported filters
t GET secrets?filters='{"name":["foo1"]}' 400
# secret list with filters
t GET secrets?filters='{"name":["mysecret"]}' 200 \
length=1 \
.[0].Spec.Name=mysecret \
.[0].Version.Index=1

t GET secrets?filters='{"name":["mysecret2"]}' 200 \
length=0 \

# secret libpod list with filters
t GET libpod/secrets/json?filters='{"name":["mysecret"]}' 200 \
length=1 \
.[0].Spec.Name=mysecret \

t GET libpod/secrets/json?filters='{"name":["mysecret2"]}' 200 \
length=0 \

# secret list with unsupported filters
t GET secrets?filters='{"label":["xyz"]}' 500

#compat api list secrets sanity checks
t GET secrets?filters='garb1age}' 500 \
.cause="invalid character 'g' looking for beginning of value"
t GET secrets?filters='{"label":["testl' 500 \
.cause="unexpected end of JSON input"

#libpod api list secrets sanity checks
t GET libpod/secrets/json?filters='garb1age}' 500 \
.cause="invalid character 'g' looking for beginning of value"
t GET libpod/secrets/json?filters='{"label":["testl' 500 \
.cause="unexpected end of JSON input"

# secret rm
t DELETE secrets/mysecret 204
Expand Down

0 comments on commit 536f23c

Please sign in to comment.