From 0abcdcf8122eadcfe9116d4401ca5f6fef425a14 Mon Sep 17 00:00:00 2001 From: Ashley Cui Date: Thu, 5 Dec 2024 23:05:19 -0500 Subject: [PATCH] Add BuildOrigin field to podman info BuiltOrigin is a field that can be set at build time by packagers. This helps us trace how and where the binary was built and installed from, allowing us to see if the issue is due to a specfic installation or a general podman bug. This field shows up in podman version and in podman info when populated. Note that podman info has a new field, Client, that only appears when running podman info using the remote client. Automatically set the BuildOrigin field when building the macOS pkginstaller to pkginstaller. Usage: make podman-remote BUILD_ORIGIN="mypackaging" Signed-off-by: Ashley Cui --- Makefile | 1 + cmd/podman/client.go | 14 ++++++---- cmd/podman/system/version.go | 2 ++ contrib/pkginstaller/package.sh | 3 +- libpod/define/version.go | 37 ++++++++++++++----------- pkg/bindings/system/info.go | 18 ++++++++++-- pkg/domain/entities/engine_container.go | 2 +- pkg/domain/entities/system.go | 1 + pkg/domain/entities/types/system.go | 5 ++++ pkg/domain/infra/abi/system.go | 15 ++++++++-- pkg/domain/infra/tunnel/system.go | 3 +- test/e2e/info_test.go | 13 +++++++++ 12 files changed, 83 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index bf81a02e02..514f85ead1 100644 --- a/Makefile +++ b/Makefile @@ -119,6 +119,7 @@ GOFLAGS ?= -trimpath LDFLAGS_PODMAN ?= \ $(if $(GIT_COMMIT),-X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT),) \ $(if $(BUILD_INFO),-X $(LIBPOD)/define.buildInfo=$(BUILD_INFO),) \ + $(if $(BUILD_ORIGIN),-X $(LIBPOD)/define.buildOrigin=$(BUILD_ORIGIN),) \ -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ -X $(LIBPOD)/config._etcDir=$(ETCDIR) \ -X $(PROJECT)/v5/pkg/systemd/quadlet._binDir=$(BINDIR) \ diff --git a/cmd/podman/client.go b/cmd/podman/client.go index b42a43520d..46c889b955 100644 --- a/cmd/podman/client.go +++ b/cmd/podman/client.go @@ -3,9 +3,10 @@ package main import "github.com/containers/podman/v5/libpod/define" type clientInfo struct { - OSArch string `json:"OS"` - Provider string `json:"provider"` - Version string `json:"version"` + OSArch string `json:"OS"` + Provider string `json:"provider"` + Version string `json:"version"` + BuildOrigin string `json:"buildOrigin,omitempty" yaml:",omitempty"` } func getClientInfo() (*clientInfo, error) { @@ -18,8 +19,9 @@ func getClientInfo() (*clientInfo, error) { return nil, err } return &clientInfo{ - OSArch: vinfo.OsArch, - Provider: p, - Version: vinfo.Version, + OSArch: vinfo.OsArch, + Provider: p, + Version: vinfo.Version, + BuildOrigin: vinfo.BuildOrigin, }, nil } diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go index 48ea151135..eb70b1ef72 100644 --- a/cmd/podman/system/version.go +++ b/cmd/podman/system/version.go @@ -97,6 +97,7 @@ API Version:\t{{.APIVersion}} Go Version:\t{{.GoVersion}} {{if .GitCommit -}}Git Commit:\t{{.GitCommit}}\n{{end -}} Built:\t{{.BuiltTime}} +{{if .BuildOrigin -}}Build Origin:\t{{.BuildOrigin}}\n{{end -}} OS/Arch:\t{{.OsArch}} {{- end}} @@ -108,6 +109,7 @@ API Version:\t{{.APIVersion}} Go Version:\t{{.GoVersion}} {{if .GitCommit -}}Git Commit:\t{{.GitCommit}}\n{{end -}} Built:\t{{.BuiltTime}} +{{if .BuildOrigin -}}Build Origin:\t{{.BuildOrigin}}\n{{end -}} OS/Arch:\t{{.OsArch}} {{- end}}{{- end}} ` diff --git a/contrib/pkginstaller/package.sh b/contrib/pkginstaller/package.sh index 42528c96c5..1b34001f6b 100755 --- a/contrib/pkginstaller/package.sh +++ b/contrib/pkginstaller/package.sh @@ -9,6 +9,7 @@ PRODUCTSIGN_IDENTITY=${PRODUCTSIGN_IDENTITY:-mock} NO_CODESIGN=${NO_CODESIGN:-0} HELPER_BINARIES_DIR="/opt/podman/bin" MACHINE_POLICY_JSON_DIR="/opt/podman/config" +BUILD_ORIGIN="pkginstaller" tmpBin="contrib/pkginstaller/tmp-bin" @@ -47,7 +48,7 @@ function build_podman() { } function build_podman_arch(){ - make -B GOARCH="$1" podman-remote HELPER_BINARIES_DIR="${HELPER_BINARIES_DIR}" + make -B GOARCH="$1" podman-remote HELPER_BINARIES_DIR="${HELPER_BINARIES_DIR}" BUILD_ORIGIN="${BUILD_ORIGIN}" make -B GOARCH="$1" podman-mac-helper mkdir -p "${tmpBin}" cp bin/darwin/podman "${tmpBin}/podman-$1" diff --git a/libpod/define/version.go b/libpod/define/version.go index 13a8fdb778..6832aeac38 100644 --- a/libpod/define/version.go +++ b/libpod/define/version.go @@ -16,18 +16,22 @@ var ( // BuildInfo is the time at which the binary was built // It will be populated by the Makefile. buildInfo string + // BuildOrigin is the packager of the binary. + // It will be populated at build-time. + buildOrigin string ) // Version is an output struct for API type Version struct { - APIVersion string - Version string - GoVersion string - GitCommit string - BuiltTime string - Built int64 - OsArch string - Os string + APIVersion string + Version string + GoVersion string + GitCommit string + BuiltTime string + Built int64 + BuildOrigin string `json:",omitempty" yaml:",omitempty"` + OsArch string + Os string } // GetVersion returns a VersionOutput struct for API and podman @@ -43,13 +47,14 @@ func GetVersion() (Version, error) { } } return Version{ - APIVersion: version.APIVersion[version.Libpod][version.CurrentAPI].String(), - Version: version.Version.String(), - GoVersion: runtime.Version(), - GitCommit: gitCommit, - BuiltTime: time.Unix(buildTime, 0).Format(time.ANSIC), - Built: buildTime, - OsArch: runtime.GOOS + "/" + runtime.GOARCH, - Os: runtime.GOOS, + APIVersion: version.APIVersion[version.Libpod][version.CurrentAPI].String(), + Version: version.Version.String(), + GoVersion: runtime.Version(), + GitCommit: gitCommit, + BuiltTime: time.Unix(buildTime, 0).Format(time.ANSIC), + Built: buildTime, + BuildOrigin: buildOrigin, + OsArch: runtime.GOOS + "/" + runtime.GOARCH, + Os: runtime.GOOS, }, nil } diff --git a/pkg/bindings/system/info.go b/pkg/bindings/system/info.go index bf70481360..740d4bb500 100644 --- a/pkg/bindings/system/info.go +++ b/pkg/bindings/system/info.go @@ -6,10 +6,11 @@ import ( "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/pkg/bindings" + "github.com/containers/podman/v5/pkg/domain/entities/types" ) // Info returns information about the libpod environment and its stores -func Info(ctx context.Context, _ *InfoOptions) (*define.Info, error) { +func Info(ctx context.Context, _ *InfoOptions) (*types.SystemInfoReport, error) { conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -21,5 +22,18 @@ func Info(ctx context.Context, _ *InfoOptions) (*define.Info, error) { defer response.Body.Close() info := define.Info{} - return &info, response.Process(&info) + if err = response.Process(&info); err != nil { + return nil, err + } + + clientVersion, err := define.GetVersion() + if err != nil { + return nil, err + } + + report := types.SystemInfoReport{ + Info: info, + Client: &clientVersion, + } + return &report, nil } diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index 0e798be4e8..d613c07699 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -61,7 +61,7 @@ type ContainerEngine interface { //nolint:interfacebloat GenerateKube(ctx context.Context, nameOrIDs []string, opts GenerateKubeOptions) (*GenerateKubeReport, error) SystemPrune(ctx context.Context, options SystemPruneOptions) (*SystemPruneReport, error) HealthCheckRun(ctx context.Context, nameOrID string, options HealthCheckOptions) (*define.HealthCheckResults, error) - Info(ctx context.Context) (*define.Info, error) + Info(ctx context.Context) (*SystemInfoReport, error) KubeApply(ctx context.Context, body io.Reader, opts ApplyOptions) error Locks(ctx context.Context) (*LocksReport, error) Migrate(ctx context.Context, options SystemMigrateOptions) error diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go index ab9c861a02..0a7c1734bf 100644 --- a/pkg/domain/entities/system.go +++ b/pkg/domain/entities/system.go @@ -20,6 +20,7 @@ type SystemVersionReport = types.SystemVersionReport type SystemUnshareOptions = types.SystemUnshareOptions type ComponentVersion = types.SystemComponentVersion type ListRegistriesReport = types.ListRegistriesReport +type SystemInfoReport = types.SystemInfoReport type AuthConfig = types.AuthConfig type AuthReport = types.AuthReport diff --git a/pkg/domain/entities/types/system.go b/pkg/domain/entities/types/system.go index 6c331cd50e..2b65823dce 100644 --- a/pkg/domain/entities/types/system.go +++ b/pkg/domain/entities/types/system.go @@ -55,6 +55,11 @@ type SystemPruneReport struct { ReclaimedSpace uint64 } +type SystemInfoReport struct { + define.Info + Client *define.Version `json:",omitempty" yaml:",omitempty"` +} + // SystemMigrateOptions describes the options needed for the // cli to migrate runtimes of containers type SystemMigrateOptions struct { diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index faa076c54d..47ff1eeb20 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -15,6 +15,7 @@ import ( "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/pkg/domain/entities" "github.com/containers/podman/v5/pkg/domain/entities/reports" + "github.com/containers/podman/v5/pkg/domain/entities/types" "github.com/containers/podman/v5/pkg/util" "github.com/containers/storage" "github.com/containers/storage/pkg/directory" @@ -22,7 +23,7 @@ import ( "github.com/sirupsen/logrus" ) -func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { +func (ic *ContainerEngine) Info(ctx context.Context) (*entities.SystemInfoReport, error) { info, err := ic.Libpod.Info() if err != nil { return nil, err @@ -36,7 +37,11 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { xdg := defaultRunPath if path, err := util.GetRootlessRuntimeDir(); err != nil { // Info is as good as we can guess... - return info, err + report := types.SystemInfoReport{ + Info: *info, + } + return &report, err + } else if path != "" { xdg = path } @@ -58,7 +63,11 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { info.Host.RemoteSocket.Exists = true } - return info, nil + report := types.SystemInfoReport{ + Info: *info, + } + + return &report, nil } // SystemPrune removes unused data from the system. Pruning pods, containers, networks, volumes and images. diff --git a/pkg/domain/infra/tunnel/system.go b/pkg/domain/infra/tunnel/system.go index 3230b31ee7..e1a7a66d5d 100644 --- a/pkg/domain/infra/tunnel/system.go +++ b/pkg/domain/infra/tunnel/system.go @@ -4,12 +4,11 @@ import ( "context" "errors" - "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/pkg/bindings/system" "github.com/containers/podman/v5/pkg/domain/entities" ) -func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { +func (ic *ContainerEngine) Info(ctx context.Context) (*entities.SystemInfoReport, error) { return system.Info(ic.ClientCtx, nil) } diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index 87c8902621..c22d48e998 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -280,6 +280,18 @@ var _ = Describe("Podman Info", func() { Expect(free1).To(Equal(free2 + 1)) }) + It("Podman info: check client information", func() { + info := podmanTest.Podman([]string{"info", "--format", "{{ .Client }}"}) + info.WaitWithDefaultTimeout() + Expect(info).To(ExitCleanly()) + // client info should only appear when using the remote client + if IsRemote() { + Expect(info.OutputToString()).ToNot(Equal("")) + } else { + Expect(info.OutputToString()).To(Equal("")) + } + }) + It("Podman info: check for client information when no system service", func() { // the output for this information is not really something we can marshall want := runtime.GOOS + "/" + runtime.GOARCH @@ -291,4 +303,5 @@ var _ = Describe("Podman Info", func() { Expect(info).ToNot(ExitCleanly()) podmanTest.StartRemoteService() // Start service again so teardown runs clean }) + })