Add --replace flag to podman secret create

Users may want to replace the secret used within containers, without
destroying the secret and recreating it.

Partial fix for https://github.com/containers/podman/issues/18667

Make sure podman --remote secret inspect and podman secret inspect
return the same error message.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2023-07-09 07:26:09 -04:00
parent 5d706eb027
commit efefd8cf5b
9 changed files with 55 additions and 3 deletions

View File

@ -55,6 +55,8 @@ func init() {
envFlagName := "env"
flags.BoolVar(&env, envFlagName, false, "Read secret data from environment variable")
flags.BoolVar(&createOpts.Replace, "replace", false, "If a secret with the same name exists, replace it")
labelFlagName := "label"
flags.StringArrayVarP(&labels, labelFlagName, "l", nil, "Specify labels on the secret")
_ = createCmd.RegisterFlagCompletionFunc(labelFlagName, completion.AutocompleteNone)

View File

@ -40,6 +40,12 @@ Print usage statement.
Add label to secret. These labels can be viewed in podman secrete inspect or ls.
#### **--replace**=*false*
If existing secret with the same name already exists, update the secret.
The `--replace` option does not change secrets within existing containers, only newly created containers.
The default is **false**.
## EXAMPLES
```

View File

@ -24,6 +24,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
Driver string `schema:"driver"`
DriverOpts map[string]string `schema:"driveropts"`
Labels map[string]string `schema:"labels"`
Replace bool `schema:"replace"`
}{
// override any golang type defaults
}
@ -36,6 +37,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
opts.Driver = query.Driver
opts.DriverOpts = query.DriverOpts
opts.Labels = query.Labels
opts.Replace = query.Replace
ic := abi.ContainerEngine{Libpod: runtime}
report, err := ic.SecretCreate(r.Context(), query.Name, r.Body, opts)

View File

@ -28,4 +28,5 @@ type CreateOptions struct {
Driver *string
DriverOpts map[string]string
Labels map[string]string
Replace *bool
}

View File

@ -76,3 +76,18 @@ func (o *CreateOptions) GetLabels() map[string]string {
}
return o.Labels
}
// WithReplace set field Replace to given value
func (o *CreateOptions) WithReplace(value bool) *CreateOptions {
o.Replace = &value
return o
}
// GetReplace returns value of field Replace
func (o *CreateOptions) GetReplace() bool {
if o.Replace == nil {
var z bool
return z
}
return *o.Replace
}

View File

@ -14,6 +14,7 @@ type SecretCreateOptions struct {
Driver string
DriverOpts map[string]string
Labels map[string]string
Replace bool
}
type SecretInspectOptions struct {

View File

@ -46,6 +46,7 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
storeOpts := secrets.StoreOptions{
DriverOpts: options.DriverOpts,
Labels: options.Labels,
Replace: options.Replace,
}
secretID, err := manager.Store(name, data, options.Driver, storeOpts)
@ -86,10 +87,13 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string
if secret.Labels == nil {
secret.Labels = make(map[string]string)
}
if secret.UpdatedAt.IsZero() {
secret.UpdatedAt = secret.CreatedAt
}
report := &entities.SecretInfoReport{
ID: secret.ID,
CreatedAt: secret.CreatedAt,
UpdatedAt: secret.CreatedAt,
UpdatedAt: secret.UpdatedAt,
Spec: entities.SecretSpec{
Name: secret.Name,
Driver: entities.SecretDriverSpec{

View File

@ -15,7 +15,8 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
WithDriver(options.Driver).
WithDriverOpts(options.DriverOpts).
WithName(name).
WithLabels(options.Labels)
WithLabels(options.Labels).
WithReplace(options.Replace)
created, err := secrets.Create(ic.ClientCtx, reader, opts)
if err != nil {
return nil, err
@ -37,7 +38,7 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string
return nil, nil, err
}
if errModel.ResponseCode == 404 {
errs = append(errs, fmt.Errorf("no such secret %q", name))
errs = append(errs, fmt.Errorf("no secret with name or id %q: no such secret ", name))
continue
}
return nil, nil, err

View File

@ -36,6 +36,26 @@ var _ = Describe("Podman secret", func() {
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
Expect(inspect.OutputToString()).To(ContainSubstring("opt1:val"))
session = podmanTest.Podman([]string{"secret", "create", "-d", "file", "--driver-opts", "opt1=val1", "a", secretFilePath})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(125))
Expect(session.ErrorToString()).To(Equal("Error: a: secret name in use"))
session = podmanTest.Podman([]string{"secret", "create", "-d", "file", "--driver-opts", "opt1=val1", "--replace", "a", secretFilePath})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(Not(Equal(secrID)))
inspect = podmanTest.Podman([]string{"secret", "inspect", "-f", "{{.Spec.Driver.Options}}", secrID})
inspect.WaitWithDefaultTimeout()
Expect(inspect).To(ExitWithError())
Expect(inspect.ErrorToString()).To(ContainSubstring(fmt.Sprintf("Error: inspecting secret: no secret with name or id %q: no such secret", secrID)))
inspect = podmanTest.Podman([]string{"secret", "inspect", "-f", "{{.Spec.Driver.Options}}", "a"})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
Expect(inspect.OutputToString()).To(ContainSubstring("opt1:val1"))
})
It("podman secret create bad name should fail", func() {