aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshley Cui <acui@redhat.com>2022-09-12 15:52:54 -0400
committerAshley Cui <acui@redhat.com>2022-09-20 16:28:00 -0400
commit9bb51e8e96f98ab74d416a9af9bd708c7c503bdf (patch)
tree602c43271772dd72cd52dca3bfb397f65ee3515e
parent8216d0ef4e8212413a650a55ce8fd02f2ca8d181 (diff)
downloadpodman-9bb51e8e96f98ab74d416a9af9bd708c7c503bdf.tar.gz
podman-9bb51e8e96f98ab74d416a9af9bd708c7c503bdf.tar.bz2
podman-9bb51e8e96f98ab74d416a9af9bd708c7c503bdf.zip
Add labels to secrets
Add --label/-l label flag to secret create, and show labels when inspecting secrets. Also allow labeling secrets via libpod/compat API. Signed-off-by: Ashley Cui <acui@redhat.com>
-rw-r--r--cmd/podman/secrets/create.go20
-rw-r--r--docs/source/markdown/podman-secret-create.1.md8
-rw-r--r--pkg/api/handlers/compat/secrets.go5
-rw-r--r--pkg/api/handlers/libpod/secrets.go2
-rw-r--r--pkg/api/server/register_secrets.go8
-rw-r--r--pkg/bindings/secrets/types.go1
-rw-r--r--pkg/bindings/secrets/types_create_options.go15
-rw-r--r--pkg/domain/entities/secrets.go4
-rw-r--r--pkg/domain/infra/abi/secrets.go5
-rw-r--r--pkg/domain/infra/tunnel/secrets.go3
-rw-r--r--test/apiv2/50-secrets.at10
-rw-r--r--test/e2e/secret_test.go37
12 files changed, 103 insertions, 15 deletions
diff --git a/cmd/podman/secrets/create.go b/cmd/podman/secrets/create.go
index 01775f563..293da2103 100644
--- a/cmd/podman/secrets/create.go
+++ b/cmd/podman/secrets/create.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v4/cmd/podman/common"
+ "github.com/containers/podman/v4/cmd/podman/parse"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/spf13/cobra"
@@ -31,6 +32,7 @@ var (
var (
createOpts = entities.SecretCreateOptions{}
env = false
+ labels []string
)
func init() {
@@ -38,21 +40,24 @@ func init() {
Command: createCmd,
Parent: secretCmd,
})
+ cfg := registry.PodmanConfig()
flags := createCmd.Flags()
driverFlagName := "driver"
- optsFlagName := "driver-opts"
-
- cfg := registry.PodmanConfig()
-
flags.StringVarP(&createOpts.Driver, driverFlagName, "d", cfg.Secrets.Driver, "Specify secret driver")
- flags.StringToStringVar(&createOpts.DriverOpts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options")
_ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone)
+
+ optsFlagName := "driver-opts"
+ flags.StringToStringVar(&createOpts.DriverOpts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options")
_ = createCmd.RegisterFlagCompletionFunc(optsFlagName, completion.AutocompleteNone)
envFlagName := "env"
flags.BoolVar(&env, envFlagName, false, "Read secret data from environment variable")
+
+ labelFlagName := "label"
+ flags.StringArrayVarP(&labels, labelFlagName, "l", nil, "Specify labels on the secret")
+ _ = createCmd.RegisterFlagCompletionFunc(labelFlagName, completion.AutocompleteNone)
}
func create(cmd *cobra.Command, args []string) error {
@@ -87,6 +92,11 @@ func create(cmd *cobra.Command, args []string) error {
reader = file
}
+ createOpts.Labels, err = parse.GetAllLabels([]string{}, labels)
+ if err != nil {
+ return fmt.Errorf("unable to process labels: %w", err)
+ }
+
report, err := registry.ContainerEngine().SecretCreate(context.Background(), name, reader, createOpts)
if err != nil {
return err
diff --git a/docs/source/markdown/podman-secret-create.1.md b/docs/source/markdown/podman-secret-create.1.md
index 1aafc6c11..fc6d72efb 100644
--- a/docs/source/markdown/podman-secret-create.1.md
+++ b/docs/source/markdown/podman-secret-create.1.md
@@ -26,16 +26,20 @@ Specify the secret driver (default **file**, which is unencrypted).
#### **--driver-opts**=*key1=val1,key2=val2*
-Specify driver specific options
+Specify driver specific options.
#### **--env**=*false*
-Read secret data from environment variable
+Read secret data from environment variable.
#### **--help**
Print usage statement.
+#### **--label**, **-l**=*key=val1,key2=val2*
+
+Add label to secret. These labels can be viewed in podman secrete inspect or ls.
+
## EXAMPLES
```
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
index 13b3c4e24..847f05f27 100644
--- a/pkg/api/handlers/compat/secrets.go
+++ b/pkg/api/handlers/compat/secrets.go
@@ -111,14 +111,11 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err))
return
}
- if len(createParams.Labels) > 0 {
- utils.Error(w, http.StatusBadRequest, fmt.Errorf("labels not supported: %w", errors.New("bad parameter")))
- return
- }
decoded, _ := base64.StdEncoding.DecodeString(createParams.Data)
reader := bytes.NewReader(decoded)
opts.Driver = createParams.Driver.Name
+ opts.Labels = createParams.Labels
ic := abi.ContainerEngine{Libpod: runtime}
report, err := ic.SecretCreate(r.Context(), createParams.Name, reader, opts)
diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go
index 6eba65f2b..c24ac8563 100644
--- a/pkg/api/handlers/libpod/secrets.go
+++ b/pkg/api/handlers/libpod/secrets.go
@@ -22,6 +22,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
Name string `schema:"name"`
Driver string `schema:"driver"`
DriverOpts map[string]string `schema:"driveropts"`
+ Labels map[string]string `schema:"labels"`
}{
// override any golang type defaults
}
@@ -33,6 +34,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
opts.Driver = query.Driver
opts.DriverOpts = query.DriverOpts
+ opts.Labels = query.Labels
ic := abi.ContainerEngine{Libpod: runtime}
report, err := ic.SecretCreate(r.Context(), query.Name, r.Body, opts)
diff --git a/pkg/api/server/register_secrets.go b/pkg/api/server/register_secrets.go
index 8918ad238..a60145958 100644
--- a/pkg/api/server/register_secrets.go
+++ b/pkg/api/server/register_secrets.go
@@ -25,6 +25,14 @@ func (s *APIServer) registerSecretHandlers(r *mux.Router) error {
// type: string
// description: Secret driver
// default: "file"
+ // - in: query
+ // name: driveropts
+ // type: string
+ // description: Secret driver options
+ // - in: query
+ // name: labels
+ // type: string
+ // description: Labels on the secret
// - in: body
// name: request
// description: Secret
diff --git a/pkg/bindings/secrets/types.go b/pkg/bindings/secrets/types.go
index 01c3c248d..d2f449556 100644
--- a/pkg/bindings/secrets/types.go
+++ b/pkg/bindings/secrets/types.go
@@ -22,4 +22,5 @@ type CreateOptions struct {
Name *string
Driver *string
DriverOpts map[string]string
+ Labels map[string]string
}
diff --git a/pkg/bindings/secrets/types_create_options.go b/pkg/bindings/secrets/types_create_options.go
index 6b1666a42..c9c88e1f3 100644
--- a/pkg/bindings/secrets/types_create_options.go
+++ b/pkg/bindings/secrets/types_create_options.go
@@ -61,3 +61,18 @@ func (o *CreateOptions) GetDriverOpts() map[string]string {
}
return o.DriverOpts
}
+
+// WithLabels set field Labels to given value
+func (o *CreateOptions) WithLabels(value map[string]string) *CreateOptions {
+ o.Labels = value
+ return o
+}
+
+// GetLabels returns value of field Labels
+func (o *CreateOptions) GetLabels() map[string]string {
+ if o.Labels == nil {
+ var z map[string]string
+ return z
+ }
+ return o.Labels
+}
diff --git a/pkg/domain/entities/secrets.go b/pkg/domain/entities/secrets.go
index d8af937a7..5686b90e9 100644
--- a/pkg/domain/entities/secrets.go
+++ b/pkg/domain/entities/secrets.go
@@ -13,6 +13,7 @@ type SecretCreateReport struct {
type SecretCreateOptions struct {
Driver string
DriverOpts map[string]string
+ Labels map[string]string
}
type SecretListRequest struct {
@@ -55,6 +56,7 @@ type SecretVersion struct {
type SecretSpec struct {
Name string
Driver SecretDriverSpec
+ Labels map[string]string
}
type SecretDriverSpec struct {
@@ -70,6 +72,8 @@ type SecretCreateRequest struct {
Data string
// Driver represents a driver (default "file")
Driver SecretDriverSpec
+ // Labels are labels on the secret
+ Labels map[string]string
}
// Secret create response
diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go
index 47159d65a..2a377288b 100644
--- a/pkg/domain/infra/abi/secrets.go
+++ b/pkg/domain/infra/abi/secrets.go
@@ -45,6 +45,7 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
storeOpts := secrets.StoreOptions{
DriverOpts: options.DriverOpts,
+ Labels: options.Labels,
}
secretID, err := manager.Store(name, data, options.Driver, storeOpts)
@@ -74,6 +75,9 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string
return nil, nil, fmt.Errorf("inspecting secret %s: %w", nameOrID, err)
}
}
+ if secret.Labels == nil {
+ secret.Labels = make(map[string]string)
+ }
report := &entities.SecretInfoReport{
ID: secret.ID,
CreatedAt: secret.CreatedAt,
@@ -84,6 +88,7 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string
Name: secret.Driver,
Options: secret.DriverOptions,
},
+ Labels: secret.Labels,
},
}
reports = append(reports, report)
diff --git a/pkg/domain/infra/tunnel/secrets.go b/pkg/domain/infra/tunnel/secrets.go
index d26718b12..aa48cb764 100644
--- a/pkg/domain/infra/tunnel/secrets.go
+++ b/pkg/domain/infra/tunnel/secrets.go
@@ -14,7 +14,8 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
opts := new(secrets.CreateOptions).
WithDriver(options.Driver).
WithDriverOpts(options.DriverOpts).
- WithName(name)
+ WithName(name).
+ WithLabels(options.Labels)
created, err := secrets.Create(ic.ClientCtx, reader, opts)
if err != nil {
return nil, err
diff --git a/test/apiv2/50-secrets.at b/test/apiv2/50-secrets.at
index ed0e8fb6b..acd8f3de9 100644
--- a/test/apiv2/50-secrets.at
+++ b/test/apiv2/50-secrets.at
@@ -7,9 +7,6 @@
t POST secrets/create Name=mysecret Data=c2VjcmV0 200\
.ID~.* \
-# secret create unsupported labels
-t POST secrets/create Name=mysecret Data=c2VjcmV0 Labels='{"fail":"fail"}' 400
-
# secret create name already in use
t POST secrets/create Name=mysecret Data=c2VjcmV0 409
@@ -59,8 +56,15 @@ t GET libpod/secrets/json?filters='garb1age}' 500 \
t GET libpod/secrets/json?filters='{"label":["testl' 500 \
.cause="unexpected end of JSON input"
+# secret with labels
+t POST secrets/create Name=labeledsecret Data=c2VjcmV0 Labels='{"foo":"bar"}' 200
+t GET secrets/labeledsecret 200 \
+ .Spec.Labels.foo=bar
+
# secret rm
t DELETE secrets/mysecret 204
+t DELETE secrets/labeledsecret 204
+
# secret rm non-existent secret
t DELETE secrets/bogus 404
diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go
index 902f422bd..91135b958 100644
--- a/test/e2e/secret_test.go
+++ b/test/e2e/secret_test.go
@@ -310,4 +310,41 @@ var _ = Describe("Podman secret", func() {
Expect(inspect.OutputToString()).To(Equal(secrID))
})
+ It("podman secret with labels", func() {
+ secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
+ err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755)
+ Expect(err).To(BeNil())
+
+ session := podmanTest.Podman([]string{"secret", "create", "--label", "foo=bar", "a", secretFilePath})
+ session.WaitWithDefaultTimeout()
+ secrID := session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ inspect := podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.Spec.Labels}}", secrID})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring("foo:bar"))
+
+ session = podmanTest.Podman([]string{"secret", "create", "--label", "foo=bar", "--label", "a:b", "b", secretFilePath})
+ session.WaitWithDefaultTimeout()
+ secrID = session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ inspect = podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.Spec.Labels}}", secrID})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring("foo:bar"))
+ Expect(inspect.OutputToString()).To(ContainSubstring("a:b"))
+
+ session = podmanTest.Podman([]string{"secret", "create", "c", secretFilePath})
+ session.WaitWithDefaultTimeout()
+ secrID = session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ inspect = podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.Spec.Labels}}", secrID})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(Equal("map[]"))
+
+ })
})