From 20523152f8dab4d092bc65155888516cdcecbd57 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Fri, 28 Feb 2025 11:04:36 +0100 Subject: [PATCH] Add "create" and "remove" events for secrets. This commit adds the "secret" Event type and emits "create" and "remove" events for this Event type when Secret is created or removed. This can be used for example by podman interfaces to view and manage secrets. Fixes: #24030 Signed-off-by: Jan Kaluza --- cmd/podman/common/completion.go | 2 +- docs/source/markdown/podman-events.1.md | 4 ++++ libpod/events.go | 10 ++++++++++ libpod/events/config.go | 2 ++ libpod/events/events.go | 4 ++++ libpod/events/logfile.go | 2 +- pkg/domain/infra/abi/secrets.go | 6 ++++++ test/e2e/secret_test.go | 14 ++++++++++++++ 8 files changed, 42 insertions(+), 2 deletions(-) diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index c90d403966..2d5e33c674 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -1522,7 +1522,7 @@ func AutocompleteEventFilter(cmd *cobra.Command, args []string, toComplete strin } eventTypes := func(_ string) ([]string, cobra.ShellCompDirective) { return []string{events.Container.String(), events.Image.String(), events.Network.String(), - events.Pod.String(), events.System.String(), events.Volume.String(), + events.Pod.String(), events.System.String(), events.Volume.String(), events.Secret.String(), }, cobra.ShellCompDirectiveNoFileComp } kv := keyValueCompletion{ diff --git a/docs/source/markdown/podman-events.1.md b/docs/source/markdown/podman-events.1.md index 24cbacdc19..4052a50f32 100644 --- a/docs/source/markdown/podman-events.1.md +++ b/docs/source/markdown/podman-events.1.md @@ -79,6 +79,10 @@ The *volume* type reports the following statuses: * prune * remove +The *secret* type reports the following statuses: + * create + * remove + #### Verbose Create Events Setting `events_container_create_inspect_data=true` in containers.conf(5) instructs Podman to create more verbose container-create events which include a JSON payload with detailed information about the containers. The JSON payload is identical to the one of podman-container-inspect(1). The associated field in journald is named `PODMAN_CONTAINER_INSPECT_DATA`. diff --git a/libpod/events.go b/libpod/events.go index 82738e36ff..71e9887ed3 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -191,6 +191,16 @@ func (v *Volume) newVolumeEvent(status events.Status) { } } +// NewSecretEvent creates a new event for a libpod secret +func (r *Runtime) NewSecretEvent(status events.Status, secretID string) { + e := events.NewEvent(status) + e.ID = secretID + e.Type = events.Secret + if err := r.eventer.Write(e); err != nil { + logrus.Errorf("Unable to write secret event: %q", err) + } +} + // Events is a wrapper function for everyone to begin tailing the events log // with options func (r *Runtime) Events(ctx context.Context, options events.ReadOptions) error { diff --git a/libpod/events/config.go b/libpod/events/config.go index ed3f4f7078..053e7e3c37 100644 --- a/libpod/events/config.go +++ b/libpod/events/config.go @@ -131,6 +131,8 @@ const ( Volume Type = "volume" // Machine - event is related to machine VM's Machine Type = "machine" + // Secret - event is related to secrets + Secret Type = "secret" // Attach ... Attach Status = "attach" diff --git a/libpod/events/events.go b/libpod/events/events.go index c69e5dab14..b237bca9ed 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -92,6 +92,8 @@ func (e *Event) ToHumanReadable(truncate bool) string { } case Volume, Machine: humanFormat = fmt.Sprintf("%s %s %s %s", e.Time, e.Type, e.Status, e.Name) + case Secret: + humanFormat = fmt.Sprintf("%s %s %s %s", e.Time, e.Type, e.Status, id) } return humanFormat } @@ -133,6 +135,8 @@ func StringToType(name string) (Type, error) { return System, nil case Volume.String(): return Volume, nil + case Secret.String(): + return Secret, nil case "": return "", ErrEventTypeBlank } diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go index 4c0dd5e226..009f6ea5d0 100644 --- a/libpod/events/logfile.go +++ b/libpod/events/logfile.go @@ -173,7 +173,7 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error { continue } switch event.Type { - case Image, Volume, Pod, Container, Network: + case Image, Volume, Pod, Container, Network, Secret: // no-op case System: begin, end, err := e.readRotateEvent(event) diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go index 5f5cfdc19b..b56da6568f 100644 --- a/pkg/domain/infra/abi/secrets.go +++ b/pkg/domain/infra/abi/secrets.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/containers/common/pkg/secrets" + "github.com/containers/podman/v5/libpod/events" "github.com/containers/podman/v5/pkg/domain/entities" "github.com/containers/podman/v5/pkg/domain/utils" ) @@ -56,6 +57,8 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader return nil, err } + ic.Libpod.NewSecretEvent(events.Create, secretID) + return &entities.SecretCreateReport{ ID: secretID, }, nil @@ -146,6 +149,9 @@ func (ic *ContainerEngine) SecretRm(ctx context.Context, nameOrIDs []string, opt continue } reports = append(reports, &entities.SecretRmReport{Err: err, ID: deletedID}) + if err == nil { + ic.Libpod.NewSecretEvent(events.Remove, deletedID) + } } return reports, nil diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go index bf373eeebe..d56a9f757f 100644 --- a/test/e2e/secret_test.go +++ b/test/e2e/secret_test.go @@ -29,6 +29,13 @@ var _ = Describe("Podman secret", func() { secrID := session.OutputToString() Expect(session).Should(ExitCleanly()) + result := podmanTest.Podman([]string{"events", "--stream=false"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(ExitCleanly()) + events := result.OutputToStringArray() + Expect(events).ToNot(BeEmpty(), "Number of events") + Expect(events).To(ContainElement(ContainSubstring(" secret create %s", secrID))) + inspect := podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.ID}}", secrID}) inspect.WaitWithDefaultTimeout() Expect(inspect).Should(ExitCleanly()) @@ -305,6 +312,13 @@ var _ = Describe("Podman secret", func() { Expect(removed).Should(ExitCleanly()) Expect(removed.OutputToString()).To(Equal(secrID)) + result := podmanTest.Podman([]string{"events", "--stream=false"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(ExitCleanly()) + events := result.OutputToStringArray() + Expect(events).ToNot(BeEmpty(), "Number of events") + Expect(events).To(ContainElement(ContainSubstring(" secret remove %s", secrID))) + session = podmanTest.Podman([]string{"secret", "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly())