Skip to content

Commit 14cf99e

Browse files
committed
podman buildx inspect support
Added support for "podman buildx inspect". The goal was to replicate the default output from "docker buildx inspect" as much as possible but a problem encountered was podman not supporting BuildKit. To replicate the output I resorted to printing the statements with default values but only changed the driver name to use podman instead of docker. Since there was no buildkit, gave it the value of "N/A" to depict it's not supported. For Platforms, I resorted to using the emulated architectures found on your linux system + the host architecture of your local machine or podman server. The bootstrap flag was also added but is considered a NOP since there is no buildkit container to run before running inspect. An extra field was added to the HostInfo struct so when you run "podman info" the emulated architectures will show, this was used so you can grab the information from the podman engine. Fixes #13014 Signed-off-by: Joshua Arrevillaga <[email protected]>
1 parent 7aa4baa commit 14cf99e

File tree

4 files changed

+154
-0
lines changed

4 files changed

+154
-0
lines changed

cmd/podman/images/buildx_inspect.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package images
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/containers/podman/v5/cmd/podman/registry"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
type buildNode struct {
12+
Name string
13+
Endpoint string
14+
Status string
15+
BuildkitVersion string
16+
Platforms []string
17+
}
18+
19+
type buildxInspectOutput struct {
20+
builderName string
21+
driverName string
22+
Nodes []buildNode
23+
}
24+
25+
var buildxInspectCmd = &cobra.Command{
26+
Use: "inspect",
27+
Short: "Inspects the current buildx builder instance",
28+
Long: "Displays information about the current builder instance (compatibility with Docker buildx inspect)",
29+
RunE: runBuildxInspect,
30+
Example: `podman buildx inspect
31+
podman buildx inspect --bootstrap`,
32+
}
33+
34+
func init() {
35+
buildxInspectCmd.Flags().Bool("bootstrap", false, "Currently a No Op for podman")
36+
registry.Commands = append(registry.Commands, registry.CliCommand{
37+
Command: buildxInspectCmd,
38+
Parent: buildxCmd,
39+
})
40+
}
41+
42+
func runBuildxInspect(cmd *cobra.Command, args []string) error {
43+
// Constants are based on default values for Docker buildx inspect.
44+
defaultNode := buildNode{
45+
Name: "default",
46+
Endpoint: "default",
47+
Status: "running",
48+
BuildkitVersion: "N/A",
49+
Platforms: []string{"unknown/unknown"},
50+
}
51+
52+
info, err := registry.ContainerEngine().Info(registry.Context())
53+
54+
if err != nil {
55+
return fmt.Errorf("retrieving podman information: %w", err)
56+
}
57+
58+
if registry.IsRemote() {
59+
runtimeOS := info.Host.OS
60+
runtimeArch := info.Host.Arch
61+
defaultNode.Platforms = []string{fmt.Sprintf("%s/%s", runtimeOS, runtimeArch)}
62+
} else {
63+
platforms := info.Host.EmulatedArchitectures
64+
platforms = append(platforms, fmt.Sprintf("%s/%s", info.Host.OS, info.Host.Arch))
65+
defaultNode.Platforms = platforms
66+
}
67+
68+
out := buildxInspectOutput{
69+
builderName: "default",
70+
driverName: "podman",
71+
Nodes: []buildNode{defaultNode},
72+
}
73+
74+
fmt.Printf("Name: %s\n", out.builderName)
75+
fmt.Printf("Driver: %s\n", out.driverName)
76+
fmt.Println()
77+
78+
fmt.Println("Nodes:")
79+
fmt.Printf("Name: %s\n", out.Nodes[0].Name)
80+
fmt.Printf("Endpoint: %s\n", out.Nodes[0].Endpoint)
81+
fmt.Printf("Status: %s\n", out.Nodes[0].Status)
82+
fmt.Printf("Buildkit version: %s\n", out.Nodes[0].BuildkitVersion)
83+
84+
fmt.Printf("Platforms: %s\n", strings.Join(out.Nodes[0].Platforms, ", "))
85+
fmt.Println("Labels: ")
86+
return nil
87+
}

libpod/define/info.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ type HostInfo struct {
6666
Uptime string `json:"uptime"`
6767
Variant string `json:"variant"`
6868
Linkmode string `json:"linkmode"`
69+
70+
EmulatedArchitectures []string `json:"emulatedArchitectures,omitempty"`
6971
}
7072

7173
// RemoteSocket describes information about the API socket

pkg/domain/infra/abi/system.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/containers/podman/v5/libpod/define"
1616
"github.com/containers/podman/v5/pkg/domain/entities"
1717
"github.com/containers/podman/v5/pkg/domain/entities/reports"
18+
"github.com/containers/podman/v5/pkg/emulation"
1819
"github.com/containers/podman/v5/pkg/util"
1920
"github.com/containers/storage"
2021
"github.com/containers/storage/pkg/directory"
@@ -27,6 +28,9 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
2728
if err != nil {
2829
return nil, err
2930
}
31+
32+
info.Host.EmulatedArchitectures = emulation.Registered()
33+
3034
info.Host.RemoteSocket = &define.RemoteSocket{Path: ic.Libpod.RemoteURI()}
3135

3236
// `podman system connection add` invokes podman via ssh to fill in connection string. Here

test/e2e/buildx_inspect_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//go:build linux || freebsd
2+
3+
package integration
4+
5+
import (
6+
"encoding/json"
7+
"regexp"
8+
"strings"
9+
10+
. "github.com/onsi/ginkgo/v2"
11+
. "github.com/onsi/gomega"
12+
)
13+
14+
var _ = Describe("Podman buildx inspect", func() {
15+
It("podman buildx inspect", func() {
16+
SkipIfRemote("binfmt-misc emulation only probed in local mode")
17+
18+
session := podmanTest.PodmanExitCleanly("buildx", "inspect")
19+
out := session.OutputToString()
20+
21+
session_bootstrap := podmanTest.PodmanExitCleanly("buildx", "inspect", "--bootstrap")
22+
out_bootstrap := session_bootstrap.OutputToString()
23+
Expect(out_bootstrap).To(Equal(out), "Output of 'podman buildx inspect' and 'podman buildx inspect --bootstrap' should be the same")
24+
25+
emuInfo := podmanTest.PodmanExitCleanly("info", "--format", "{{json .Host.EmulatedArchitectures}}")
26+
var emuArchs []string
27+
Expect(json.Unmarshal([]byte(emuInfo.OutputToString()), &emuArchs)).To(Succeed())
28+
29+
nativeInfo := podmanTest.PodmanExitCleanly("info", "--format", "{{.Host.OS}}/{{.Host.Arch}}")
30+
nativePlat := strings.TrimSpace(nativeInfo.OutputToString())
31+
Expect(nativePlat).ToNot(BeEmpty())
32+
33+
expected := append(emuArchs, nativePlat)
34+
35+
for _, p := range expected {
36+
re := regexp.MustCompile(`(?s)Platforms:.*\b` + regexp.QuoteMeta(p) + `\b`)
37+
Expect(out).To(MatchRegexp(re.String()), "missing %q in:\n%s", p, out)
38+
}
39+
})
40+
41+
It("podman-remote buildx inspect", func() {
42+
session := podmanTest.PodmanExitCleanly("buildx", "inspect")
43+
out := session.OutputToString()
44+
45+
session_bootstrap := podmanTest.PodmanExitCleanly("buildx", "inspect", "--bootstrap")
46+
out_bootstrap := session_bootstrap.OutputToString()
47+
Expect(out_bootstrap).To(Equal(out), "Output of 'podman-remote buildx inspect' and 'podman-remote buildx inspect --bootstrap' should be the same")
48+
49+
emuInfo := podmanTest.PodmanExitCleanly("info", "--format", "{{json .Host.EmulatedArchitectures}}")
50+
var emuArchs []string
51+
Expect(json.Unmarshal([]byte(emuInfo.OutputToString()), &emuArchs)).To(Succeed())
52+
Expect(emuArchs).To(BeEmpty())
53+
54+
nativeInfo := podmanTest.PodmanExitCleanly("info", "--format", "{{.Host.OS}}/{{.Host.Arch}}")
55+
nativePlatform := strings.TrimSpace(nativeInfo.OutputToString())
56+
Expect(nativePlatform).ToNot(BeEmpty())
57+
58+
re := regexp.MustCompile(`(?s)Platforms:.*\b` + regexp.QuoteMeta(nativePlatform) + `\b`)
59+
Expect(out).To(MatchRegexp(re.String()), "missing native %q in:\n%s", nativePlatform, out)
60+
})
61+
})

0 commit comments

Comments
 (0)