From b56b4b53744c59cad942278ff34a0b0616a7aa60 Mon Sep 17 00:00:00 2001
From: Tino Rusch <tino.rusch@gmail.com>
Date: Sun, 20 Jun 2021 16:11:54 +0200
Subject: read secret config from config file if no user data.

feat: read secret config from config file if the user hasn't entered
explicit config values

feat: allow to specify `--driver-opts opt1=val1,opt2=val2` in the secret
create command to allow overriding the default values

fix: show driver options in `podman secret inspect`

Signed-off-by: Tino Rusch <tino.rusch@gmail.com>
---
 cmd/podman/secrets/create.go                   |  8 +++++-
 docs/source/markdown/podman-secret-create.1.md |  4 +++
 pkg/api/handlers/libpod/secrets.go             | 16 ++++++++++--
 pkg/bindings/internal/util/util.go             |  4 +--
 pkg/bindings/secrets/types.go                  |  5 ++--
 pkg/bindings/secrets/types_create_options.go   | 36 +++++++++++++++++++-------
 pkg/domain/entities/secrets.go                 |  1 +
 pkg/domain/infra/abi/secrets.go                | 26 +++++++++++++++----
 pkg/domain/infra/tunnel/secrets.go             | 10 +++++--
 test/e2e/secret_test.go                        |  6 ++++-
 10 files changed, 91 insertions(+), 25 deletions(-)

diff --git a/cmd/podman/secrets/create.go b/cmd/podman/secrets/create.go
index f5739e99a..8c268615c 100644
--- a/cmd/podman/secrets/create.go
+++ b/cmd/podman/secrets/create.go
@@ -42,8 +42,14 @@ func init() {
 	flags := createCmd.Flags()
 
 	driverFlagName := "driver"
-	flags.StringVar(&createOpts.Driver, driverFlagName, "file", "Specify secret driver")
+	optsFlagName := "driver-opts"
+
+	cfg := registry.PodmanConfig()
+
+	flags.StringVar(&createOpts.Driver, driverFlagName, cfg.Secrets.Driver, "Specify secret driver")
+	flags.StringToStringVar(&createOpts.Opts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options")
 	_ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone)
+	_ = createCmd.RegisterFlagCompletionFunc(optsFlagName, completion.AutocompleteNone)
 
 	envFlagName := "env"
 	flags.BoolVar(&env, envFlagName, false, "Read secret data from environment variable")
diff --git a/docs/source/markdown/podman-secret-create.1.md b/docs/source/markdown/podman-secret-create.1.md
index c70d80719..712ca4aaa 100644
--- a/docs/source/markdown/podman-secret-create.1.md
+++ b/docs/source/markdown/podman-secret-create.1.md
@@ -28,6 +28,10 @@ Read secret data from environment variable
 
 Specify the secret driver (default **file**, which is unencrypted).
 
+#### **--driver-opts**=*key1=val1,key2=val2*
+
+Specify driver specific options
+
 #### **--help**
 
 Print usage statement.
diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go
index e7f4397ea..867a0b957 100644
--- a/pkg/api/handlers/libpod/secrets.go
+++ b/pkg/api/handlers/libpod/secrets.go
@@ -1,7 +1,9 @@
 package libpod
 
 import (
+	"encoding/json"
 	"net/http"
+	"reflect"
 
 	"github.com/containers/podman/v3/libpod"
 	"github.com/containers/podman/v3/pkg/api/handlers/utils"
@@ -16,9 +18,17 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
 		runtime = r.Context().Value("runtime").(*libpod.Runtime)
 		decoder = r.Context().Value("decoder").(*schema.Decoder)
 	)
+
+	decoder.RegisterConverter(map[string]string{}, func(str string) reflect.Value {
+		res := make(map[string]string)
+		json.Unmarshal([]byte(str), &res)
+		return reflect.ValueOf(res)
+	})
+
 	query := struct {
-		Name   string `schema:"name"`
-		Driver string `schema:"driver"`
+		Name       string            `schema:"name"`
+		Driver     string            `schema:"driver"`
+		DriverOpts map[string]string `schema:"driveropts"`
 	}{
 		// override any golang type defaults
 	}
@@ -28,7 +38,9 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
 			errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
 		return
 	}
+
 	opts.Driver = query.Driver
+	opts.Opts = query.DriverOpts
 
 	ic := abi.ContainerEngine{Libpod: runtime}
 	report, err := ic.SecretCreate(r.Context(), query.Name, r.Body, opts)
diff --git a/pkg/bindings/internal/util/util.go b/pkg/bindings/internal/util/util.go
index c1961308e..ef93d6e25 100644
--- a/pkg/bindings/internal/util/util.go
+++ b/pkg/bindings/internal/util/util.go
@@ -85,10 +85,10 @@ func ToParams(o interface{}) (url.Values, error) {
 				}
 			}
 		case f.Kind() == reflect.Map:
-			lowerCaseKeys := make(map[string][]string)
+			lowerCaseKeys := make(map[string]interface{})
 			iter := f.MapRange()
 			for iter.Next() {
-				lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface().([]string)
+				lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface()
 			}
 			s, err := json.MarshalToString(lowerCaseKeys)
 			if err != nil {
diff --git a/pkg/bindings/secrets/types.go b/pkg/bindings/secrets/types.go
index a98e894dc..a64dea1b4 100644
--- a/pkg/bindings/secrets/types.go
+++ b/pkg/bindings/secrets/types.go
@@ -18,6 +18,7 @@ type RemoveOptions struct {
 //go:generate go run ../generator/generator.go CreateOptions
 // CreateOptions are optional options for Creating secrets
 type CreateOptions struct {
-	Driver *string
-	Name   *string
+	Name       *string
+	Driver     *string
+	DriverOpts map[string]string
 }
diff --git a/pkg/bindings/secrets/types_create_options.go b/pkg/bindings/secrets/types_create_options.go
index ea5bd3039..28d0c4e83 100644
--- a/pkg/bindings/secrets/types_create_options.go
+++ b/pkg/bindings/secrets/types_create_options.go
@@ -20,6 +20,22 @@ func (o *CreateOptions) ToParams() (url.Values, error) {
 	return util.ToParams(o)
 }
 
+// WithName
+func (o *CreateOptions) WithName(value string) *CreateOptions {
+	v := &value
+	o.Name = v
+	return o
+}
+
+// GetName
+func (o *CreateOptions) GetName() string {
+	var name string
+	if o.Name == nil {
+		return name
+	}
+	return *o.Name
+}
+
 // WithDriver
 func (o *CreateOptions) WithDriver(value string) *CreateOptions {
 	v := &value
@@ -36,18 +52,18 @@ func (o *CreateOptions) GetDriver() string {
 	return *o.Driver
 }
 
-// WithName
-func (o *CreateOptions) WithName(value string) *CreateOptions {
-	v := &value
-	o.Name = v
+// WithDriverOpts
+func (o *CreateOptions) WithDriverOpts(value map[string]string) *CreateOptions {
+	v := value
+	o.DriverOpts = v
 	return o
 }
 
-// GetName
-func (o *CreateOptions) GetName() string {
-	var name string
-	if o.Name == nil {
-		return name
+// GetDriverOpts
+func (o *CreateOptions) GetDriverOpts() map[string]string {
+	var driverOpts map[string]string
+	if o.DriverOpts == nil {
+		return driverOpts
 	}
-	return *o.Name
+	return o.DriverOpts
 }
diff --git a/pkg/domain/entities/secrets.go b/pkg/domain/entities/secrets.go
index 8ede981da..e69b0a07c 100644
--- a/pkg/domain/entities/secrets.go
+++ b/pkg/domain/entities/secrets.go
@@ -12,6 +12,7 @@ type SecretCreateReport struct {
 
 type SecretCreateOptions struct {
 	Driver string
+	Opts   map[string]string
 }
 
 type SecretListRequest struct {
diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go
index 1e1cbc70f..fa28a9b51 100644
--- a/pkg/domain/infra/abi/secrets.go
+++ b/pkg/domain/infra/abi/secrets.go
@@ -17,15 +17,30 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
 	if err != nil {
 		return nil, err
 	}
-	driverOptions := make(map[string]string)
 
+	// set defaults from config for the case they are not set by an upper layer
+	// (-> i.e. tests that talk directly to the api)
+	cfg, err := ic.Libpod.GetConfig()
+	if err != nil {
+		return nil, err
+	}
 	if options.Driver == "" {
-		options.Driver = "file"
+		options.Driver = cfg.Secrets.Driver
+	}
+	if len(options.Opts) == 0 {
+		options.Opts = cfg.Secrets.Opts
+	}
+	if options.Opts == nil {
+		options.Opts = make(map[string]string)
 	}
+
 	if options.Driver == "file" {
-		driverOptions["path"] = filepath.Join(secretsPath, "filedriver")
+		if _, ok := options.Opts["path"]; !ok {
+			options.Opts["path"] = filepath.Join(secretsPath, "filedriver")
+		}
 	}
-	secretID, err := manager.Store(name, data, options.Driver, driverOptions)
+
+	secretID, err := manager.Store(name, data, options.Driver, options.Opts)
 	if err != nil {
 		return nil, err
 	}
@@ -58,7 +73,8 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string
 			Spec: entities.SecretSpec{
 				Name: secret.Name,
 				Driver: entities.SecretDriverSpec{
-					Name: secret.Driver,
+					Name:    secret.Driver,
+					Options: secret.DriverOptions,
 				},
 			},
 		}
diff --git a/pkg/domain/infra/tunnel/secrets.go b/pkg/domain/infra/tunnel/secrets.go
index 1153f490e..8cdc220a4 100644
--- a/pkg/domain/infra/tunnel/secrets.go
+++ b/pkg/domain/infra/tunnel/secrets.go
@@ -11,8 +11,14 @@ import (
 )
 
 func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader io.Reader, options entities.SecretCreateOptions) (*entities.SecretCreateReport, error) {
-	opts := new(secrets.CreateOptions).WithDriver(options.Driver).WithName(name)
-	created, _ := secrets.Create(ic.ClientCtx, reader, opts)
+	opts := new(secrets.CreateOptions).
+		WithDriver(options.Driver).
+		WithDriverOpts(options.Opts).
+		WithName(name)
+	created, err := secrets.Create(ic.ClientCtx, reader, opts)
+	if err != nil {
+		return nil, err
+	}
 	return created, nil
 }
 
diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go
index b54b959bf..392129784 100644
--- a/test/e2e/secret_test.go
+++ b/test/e2e/secret_test.go
@@ -39,7 +39,7 @@ var _ = Describe("Podman secret", func() {
 		err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755)
 		Expect(err).To(BeNil())
 
-		session := podmanTest.Podman([]string{"secret", "create", "a", secretFilePath})
+		session := podmanTest.Podman([]string{"secret", "create", "--driver-opts", "opt1=val", "a", secretFilePath})
 		session.WaitWithDefaultTimeout()
 		secrID := session.OutputToString()
 		Expect(session.ExitCode()).To(Equal(0))
@@ -48,6 +48,10 @@ var _ = Describe("Podman secret", func() {
 		inspect.WaitWithDefaultTimeout()
 		Expect(inspect.ExitCode()).To(Equal(0))
 		Expect(inspect.OutputToString()).To(Equal(secrID))
+		inspect = podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.Spec.Driver.Options}}", secrID})
+		inspect.WaitWithDefaultTimeout()
+		Expect(inspect.ExitCode()).To(Equal(0))
+		Expect(inspect.OutputToString()).To(ContainSubstring("opt1:val"))
 	})
 
 	It("podman secret create bad name should fail", func() {
-- 
cgit v1.2.3-54-g00ecf


From e7507fe7cf2f35e332f58ae632882f29395e4c59 Mon Sep 17 00:00:00 2001
From: Tino Rusch <tino.rusch@gmail.com>
Date: Fri, 25 Jun 2021 08:33:15 +0200
Subject: make DriverOpts name consistent.

Signed-off-by: Tino Rusch <tino.rusch@gmail.com>
---
 cmd/podman/secrets/create.go       |  2 +-
 pkg/api/handlers/libpod/secrets.go |  2 +-
 pkg/domain/entities/secrets.go     |  4 ++--
 pkg/domain/infra/abi/secrets.go    | 14 +++++++-------
 pkg/domain/infra/tunnel/secrets.go |  2 +-
 5 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/cmd/podman/secrets/create.go b/cmd/podman/secrets/create.go
index 8c268615c..f9846f9fb 100644
--- a/cmd/podman/secrets/create.go
+++ b/cmd/podman/secrets/create.go
@@ -47,7 +47,7 @@ func init() {
 	cfg := registry.PodmanConfig()
 
 	flags.StringVar(&createOpts.Driver, driverFlagName, cfg.Secrets.Driver, "Specify secret driver")
-	flags.StringToStringVar(&createOpts.Opts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options")
+	flags.StringToStringVar(&createOpts.DriverOpts, optsFlagName, cfg.Secrets.Opts, "Specify driver specific options")
 	_ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone)
 	_ = createCmd.RegisterFlagCompletionFunc(optsFlagName, completion.AutocompleteNone)
 
diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go
index 867a0b957..7086d9e38 100644
--- a/pkg/api/handlers/libpod/secrets.go
+++ b/pkg/api/handlers/libpod/secrets.go
@@ -40,7 +40,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
 	}
 
 	opts.Driver = query.Driver
-	opts.Opts = query.DriverOpts
+	opts.DriverOpts = query.DriverOpts
 
 	ic := abi.ContainerEngine{Libpod: runtime}
 	report, err := ic.SecretCreate(r.Context(), query.Name, r.Body, opts)
diff --git a/pkg/domain/entities/secrets.go b/pkg/domain/entities/secrets.go
index e69b0a07c..56a1465b7 100644
--- a/pkg/domain/entities/secrets.go
+++ b/pkg/domain/entities/secrets.go
@@ -11,8 +11,8 @@ type SecretCreateReport struct {
 }
 
 type SecretCreateOptions struct {
-	Driver string
-	Opts   map[string]string
+	Driver     string
+	DriverOpts map[string]string
 }
 
 type SecretListRequest struct {
diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go
index fa28a9b51..0bdb4ce60 100644
--- a/pkg/domain/infra/abi/secrets.go
+++ b/pkg/domain/infra/abi/secrets.go
@@ -27,20 +27,20 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
 	if options.Driver == "" {
 		options.Driver = cfg.Secrets.Driver
 	}
-	if len(options.Opts) == 0 {
-		options.Opts = cfg.Secrets.Opts
+	if len(options.DriverOpts) == 0 {
+		options.DriverOpts = cfg.Secrets.Opts
 	}
-	if options.Opts == nil {
-		options.Opts = make(map[string]string)
+	if options.DriverOpts == nil {
+		options.DriverOpts = make(map[string]string)
 	}
 
 	if options.Driver == "file" {
-		if _, ok := options.Opts["path"]; !ok {
-			options.Opts["path"] = filepath.Join(secretsPath, "filedriver")
+		if _, ok := options.DriverOpts["path"]; !ok {
+			options.DriverOpts["path"] = filepath.Join(secretsPath, "filedriver")
 		}
 	}
 
-	secretID, err := manager.Store(name, data, options.Driver, options.Opts)
+	secretID, err := manager.Store(name, data, options.Driver, options.DriverOpts)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/domain/infra/tunnel/secrets.go b/pkg/domain/infra/tunnel/secrets.go
index 8cdc220a4..ecbb80931 100644
--- a/pkg/domain/infra/tunnel/secrets.go
+++ b/pkg/domain/infra/tunnel/secrets.go
@@ -13,7 +13,7 @@ import (
 func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader io.Reader, options entities.SecretCreateOptions) (*entities.SecretCreateReport, error) {
 	opts := new(secrets.CreateOptions).
 		WithDriver(options.Driver).
-		WithDriverOpts(options.Opts).
+		WithDriverOpts(options.DriverOpts).
 		WithName(name)
 	created, err := secrets.Create(ic.ClientCtx, reader, opts)
 	if err != nil {
-- 
cgit v1.2.3-54-g00ecf