summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorJakub Guzik <jakubmguzik@gmail.com>2021-09-02 23:01:37 +0200
committerJakub Guzik <jakubmguzik@gmail.com>2021-09-03 10:29:31 +0200
commitd346e6e734dbaac911de0d774a5d8703e2abc83d (patch)
tree0bd5ac510effcc97b70341b6a719cbfcfbc058bc /pkg
parent469900406ac51332785455bc8668bd1c053badd6 (diff)
downloadpodman-d346e6e734dbaac911de0d774a5d8703e2abc83d.tar.gz
podman-d346e6e734dbaac911de0d774a5d8703e2abc83d.tar.bz2
podman-d346e6e734dbaac911de0d774a5d8703e2abc83d.zip
Add filtering functionality to http api secrets list
Filtering is missing in both compat API and libpod API, while docker has filtering functinality. This commit enables filtering option using name and id in both libpod and http API. Signed-off-by: Jakub Guzik <jakubmguzik@gmail.com>
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/secrets.go22
-rw-r--r--pkg/api/server/register_secrets.go16
-rw-r--r--pkg/bindings/secrets/secrets.go6
-rw-r--r--pkg/bindings/secrets/types.go1
-rw-r--r--pkg/bindings/secrets/types_list_options.go16
-rw-r--r--pkg/domain/entities/engine_container.go2
-rw-r--r--pkg/domain/entities/secrets.go2
-rw-r--r--pkg/domain/infra/abi/secrets.go31
-rw-r--r--pkg/domain/infra/tunnel/secrets.go5
-rw-r--r--pkg/domain/utils/secrets_filters.go24
10 files changed, 94 insertions, 31 deletions
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
index 86e3887a4..7dd17ea94 100644
--- a/pkg/api/handlers/compat/secrets.go
+++ b/pkg/api/handlers/compat/secrets.go
@@ -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
diff --git a/pkg/api/server/register_secrets.go b/pkg/api/server/register_secrets.go
index ca9790e93..129912179 100644
--- a/pkg/api/server/register_secrets.go
+++ b/pkg/api/server/register_secrets.go
@@ -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:
@@ -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:
diff --git a/pkg/bindings/secrets/secrets.go b/pkg/bindings/secrets/secrets.go
index b741d3e5c..c439971c9 100644
--- a/pkg/bindings/secrets/secrets.go
+++ b/pkg/bindings/secrets/secrets.go
@@ -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
}
diff --git a/pkg/bindings/secrets/types.go b/pkg/bindings/secrets/types.go
index a64dea1b4..01c3c248d 100644
--- a/pkg/bindings/secrets/types.go
+++ b/pkg/bindings/secrets/types.go
@@ -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
diff --git a/pkg/bindings/secrets/types_list_options.go b/pkg/bindings/secrets/types_list_options.go
index 568e021a8..e4501dde8 100644
--- a/pkg/bindings/secrets/types_list_options.go
+++ b/pkg/bindings/secrets/types_list_options.go
@@ -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
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index bd011d309..d03e2f719 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -85,7 +85,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)
diff --git a/pkg/domain/entities/secrets.go b/pkg/domain/entities/secrets.go
index 56a1465b7..55b470d7b 100644
--- a/pkg/domain/entities/secrets.go
+++ b/pkg/domain/entities/secrets.go
@@ -16,7 +16,7 @@ type SecretCreateOptions struct {
}
type SecretListRequest struct {
- Filters map[string]string
+ Filters map[string][]string
}
type SecretListReport struct {
diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go
index 0bdb4ce60..2bf8eaae3 100644
--- a/pkg/domain/infra/abi/secrets.go
+++ b/pkg/domain/infra/abi/secrets.go
@@ -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"
)
@@ -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
@@ -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
}
diff --git a/pkg/domain/infra/tunnel/secrets.go b/pkg/domain/infra/tunnel/secrets.go
index ecbb80931..6337c7fbe 100644
--- a/pkg/domain/infra/tunnel/secrets.go
+++ b/pkg/domain/infra/tunnel/secrets.go
@@ -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
}
diff --git a/pkg/domain/utils/secrets_filters.go b/pkg/domain/utils/secrets_filters.go
new file mode 100644
index 000000000..3ff7c7530
--- /dev/null
+++ b/pkg/domain/utils/secrets_filters.go
@@ -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
+}