github.com/containers/podman/v4@v4.9.4/test/e2e/info_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "os/user" 8 "path/filepath" 9 "runtime" 10 "strconv" 11 12 . "github.com/containers/podman/v4/test/utils" 13 . "github.com/onsi/ginkgo/v2" 14 . "github.com/onsi/gomega" 15 . "github.com/onsi/gomega/gexec" 16 ) 17 18 var _ = Describe("Podman Info", func() { 19 20 It("podman info --format json", func() { 21 tests := []struct { 22 input string 23 success bool 24 exitCode int 25 }{ 26 {"json", true, 0}, 27 {" json", true, 0}, 28 {"json ", true, 0}, 29 {" json ", true, 0}, 30 {"{{json .}}", true, 0}, 31 {"{{ json .}}", true, 0}, 32 {"{{json . }}", true, 0}, 33 {" {{ json . }} ", true, 0}, 34 {"{{json }}", true, 0}, 35 {"{{json .", false, 125}, 36 {"json . }}", false, 0}, // without opening {{ template seen as string literal 37 } 38 for _, tt := range tests { 39 session := podmanTest.Podman([]string{"info", "--format", tt.input}) 40 session.WaitWithDefaultTimeout() 41 42 desc := fmt.Sprintf("JSON test(%q)", tt.input) 43 Expect(session).Should(Exit(tt.exitCode), desc) 44 Expect(session.IsJSONOutputValid()).To(Equal(tt.success), desc) 45 } 46 }) 47 48 It("podman info --format GO template", func() { 49 session := podmanTest.Podman([]string{"info", "--format", "{{.Store.GraphRoot}}"}) 50 session.WaitWithDefaultTimeout() 51 Expect(session).Should(ExitCleanly()) 52 }) 53 54 It("podman info --format GO template", func() { 55 session := podmanTest.Podman([]string{"info", "--format", "{{.Registries}}"}) 56 session.WaitWithDefaultTimeout() 57 Expect(session).Should(ExitCleanly()) 58 Expect(session.OutputToString()).To(ContainSubstring("registry")) 59 }) 60 61 It("podman info --format GO template plugins", func() { 62 session := podmanTest.Podman([]string{"info", "--format", "{{.Plugins}}"}) 63 session.WaitWithDefaultTimeout() 64 Expect(session).Should(ExitCleanly()) 65 Expect(session.OutputToString()).To(ContainSubstring("local")) 66 Expect(session.OutputToString()).To(ContainSubstring("journald")) 67 Expect(session.OutputToString()).To(ContainSubstring("bridge")) 68 }) 69 70 It("podman info rootless storage path", func() { 71 SkipIfNotRootless("test of rootless_storage_path is only meaningful as rootless") 72 SkipIfRemote("Only tests storage on local client") 73 configPath := filepath.Join(podmanTest.TempDir, ".config", "containers", "storage.conf") 74 os.Setenv("CONTAINERS_STORAGE_CONF", configPath) 75 defer func() { 76 os.Unsetenv("CONTAINERS_STORAGE_CONF") 77 }() 78 err := os.RemoveAll(filepath.Dir(configPath)) 79 Expect(err).ToNot(HaveOccurred()) 80 81 err = os.MkdirAll(filepath.Dir(configPath), os.ModePerm) 82 Expect(err).ToNot(HaveOccurred()) 83 84 rootlessStoragePath := `"/tmp/$HOME/$USER/$UID/storage"` 85 driver := `"overlay"` 86 storageOpt := `"/usr/bin/fuse-overlayfs"` 87 storageConf := []byte(fmt.Sprintf("[storage]\ndriver=%s\nrootless_storage_path=%s\n[storage.options]\nmount_program=%s", driver, rootlessStoragePath, storageOpt)) 88 err = os.WriteFile(configPath, storageConf, os.ModePerm) 89 Expect(err).ToNot(HaveOccurred()) 90 91 u, err := user.Current() 92 Expect(err).ToNot(HaveOccurred()) 93 94 // Cannot use podmanTest.Podman() and test for storage path 95 expect := filepath.Join("/tmp", os.Getenv("HOME"), u.Username, u.Uid, "storage") 96 podmanPath := podmanTest.PodmanTest.PodmanBinary 97 cmd := exec.Command(podmanPath, "info", "--format", "{{.Store.GraphRoot -}}") 98 out, err := cmd.CombinedOutput() 99 Expect(err).ToNot(HaveOccurred()) 100 Expect(string(out)).To(Equal(expect)) 101 }) 102 103 It("check RemoteSocket ", func() { 104 session := podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Path}}"}) 105 session.WaitWithDefaultTimeout() 106 Expect(session).Should(ExitCleanly()) 107 Expect(session.OutputToString()).To(MatchRegexp("/run/.*podman.*sock")) 108 109 session = podmanTest.Podman([]string{"info", "--format", "{{.Host.ServiceIsRemote}}"}) 110 session.WaitWithDefaultTimeout() 111 Expect(session).Should(ExitCleanly()) 112 if podmanTest.RemoteTest { 113 Expect(session.OutputToString()).To(Equal("true")) 114 } else { 115 Expect(session.OutputToString()).To(Equal("false")) 116 } 117 118 session = podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Exists}}"}) 119 session.WaitWithDefaultTimeout() 120 Expect(session).Should(ExitCleanly()) 121 if IsRemote() { 122 Expect(session.OutputToString()).To(ContainSubstring("true")) 123 } else { 124 Expect(session.OutputToString()).To(ContainSubstring("false")) 125 } 126 127 }) 128 129 It("Podman info must contain cgroupControllers with RelevantControllers", func() { 130 SkipIfRootless("Hard to tell which controllers are going to be enabled for rootless") 131 SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") 132 session := podmanTest.Podman([]string{"info", "--format", "{{.Host.CgroupControllers}}"}) 133 session.WaitWithDefaultTimeout() 134 Expect(session).To(ExitCleanly()) 135 Expect(session.OutputToString()).To(ContainSubstring("memory")) 136 Expect(session.OutputToString()).To(ContainSubstring("pids")) 137 }) 138 139 It("Podman info: check desired runtime", func() { 140 // defined in .cirrus.yml 141 want := os.Getenv("CI_DESIRED_RUNTIME") 142 if want == "" { 143 if os.Getenv("CIRRUS_CI") == "" { 144 Skip("CI_DESIRED_RUNTIME is not set--this is OK because we're not running under Cirrus") 145 } 146 Fail("CIRRUS_CI is set, but CI_DESIRED_RUNTIME is not! See #14912") 147 } 148 session := podmanTest.Podman([]string{"info", "--format", "{{.Host.OCIRuntime.Name}}"}) 149 session.WaitWithDefaultTimeout() 150 Expect(session).To(ExitCleanly()) 151 Expect(session.OutputToString()).To(Equal(want)) 152 }) 153 154 It("Podman info: check desired network backend", func() { 155 // defined in .cirrus.yml 156 want := os.Getenv("CI_DESIRED_NETWORK") 157 if want == "" { 158 if os.Getenv("CIRRUS_CI") == "" { 159 Skip("CI_DESIRED_NETWORK is not set--this is OK because we're not running under Cirrus") 160 } 161 Fail("CIRRUS_CI is set, but CI_DESIRED_NETWORK is not! See #16389") 162 } 163 session := podmanTest.Podman([]string{"info", "--format", "{{.Host.NetworkBackend}}"}) 164 session.WaitWithDefaultTimeout() 165 Expect(session).To(ExitCleanly()) 166 Expect(session.OutputToString()).To(Equal(want)) 167 168 session = podmanTest.Podman([]string{"info", "--format", "{{.Host.NetworkBackendInfo.Backend}}"}) 169 session.WaitWithDefaultTimeout() 170 Expect(session).To(ExitCleanly()) 171 Expect(session.OutputToString()).To(Equal(want)) 172 }) 173 174 It("Podman info: check desired database backend", func() { 175 // defined in .cirrus.yml 176 want := os.Getenv("CI_DESIRED_DATABASE") 177 if want == "" { 178 if os.Getenv("CIRRUS_CI") == "" { 179 Skip("CI_DESIRED_DATABASE is not set--this is OK because we're not running under Cirrus") 180 } 181 Fail("CIRRUS_CI is set, but CI_DESIRED_DATABASE is not! See #16389") 182 } 183 session := podmanTest.Podman([]string{"info", "--format", "{{.Host.DatabaseBackend}}"}) 184 session.WaitWithDefaultTimeout() 185 Expect(session).To(ExitCleanly()) 186 Expect(session.OutputToString()).To(Equal(want)) 187 }) 188 189 It("podman --db-backend info basic check", func() { 190 SkipIfRemote("--db-backend only supported on the local client") 191 type argWant struct { 192 arg string 193 want string 194 } 195 backends := []argWant{ 196 // default should be sqlite 197 {arg: "", want: "sqlite"}, 198 {arg: "boltdb", want: "boltdb"}, 199 // now because a boltdb exists it should use boltdb when default is requested 200 {arg: "", want: "boltdb"}, 201 {arg: "sqlite", want: "sqlite"}, 202 } 203 204 for _, tt := range backends { 205 session := podmanTest.Podman([]string{"--db-backend", tt.arg, "--log-level=info", "info", "--format", "{{.Host.DatabaseBackend}}"}) 206 session.WaitWithDefaultTimeout() 207 Expect(session).To(Exit(0)) 208 Expect(session.OutputToString()).To(Equal(tt.want)) 209 Expect(session.ErrorToString()).To(ContainSubstring("Using %s as database backend", tt.want)) 210 } 211 212 // make sure we get an error for bogus values 213 session := podmanTest.Podman([]string{"--db-backend", "bogus", "info", "--format", "{{.Host.DatabaseBackend}}"}) 214 session.WaitWithDefaultTimeout() 215 Expect(session).To(Exit(125)) 216 Expect(session.ErrorToString()).To(Equal("Error: unsupported database backend: \"bogus\"")) 217 }) 218 219 It("Podman info: check desired storage driver", func() { 220 // defined in .cirrus.yml 221 want := os.Getenv("CI_DESIRED_STORAGE") 222 if want == "" { 223 if os.Getenv("CIRRUS_CI") == "" { 224 Skip("CI_DESIRED_STORAGE is not set--this is OK because we're not running under Cirrus") 225 } 226 Fail("CIRRUS_CI is set, but CI_DESIRED_STORAGE is not! See #20161") 227 } 228 session := podmanTest.Podman([]string{"info", "--format", "{{.Store.GraphDriverName}}"}) 229 session.WaitWithDefaultTimeout() 230 Expect(session).To(ExitCleanly()) 231 Expect(session.OutputToString()).To(Equal(want), ".Store.GraphDriverName from podman info") 232 }) 233 234 It("Podman info: check lock count", Serial, func() { 235 // This should not run on architectures and OSes that use the file locks backend. 236 // Which, for now, is Linux + RISCV and FreeBSD, neither of which are in CI - so 237 // no skips. 238 info1 := podmanTest.Podman([]string{"info", "--format", "{{ .Host.FreeLocks }}"}) 239 info1.WaitWithDefaultTimeout() 240 Expect(info1).To(ExitCleanly()) 241 free1, err := strconv.Atoi(info1.OutputToString()) 242 Expect(err).To(Not(HaveOccurred())) 243 244 ctr := podmanTest.Podman([]string{"create", ALPINE, "top"}) 245 ctr.WaitWithDefaultTimeout() 246 Expect(ctr).To(ExitCleanly()) 247 248 info2 := podmanTest.Podman([]string{"info", "--format", "{{ .Host.FreeLocks }}"}) 249 info2.WaitWithDefaultTimeout() 250 Expect(info2).To(ExitCleanly()) 251 free2, err := strconv.Atoi(info2.OutputToString()) 252 Expect(err).To(Not(HaveOccurred())) 253 254 // Effectively, we are checking that 1 lock has been taken. 255 // We do this by comparing the number of locks after (plus 1), to the number of locks before. 256 // Don't check absolute numbers because there is a decent chance of contamination, containers that were never removed properly, etc. 257 Expect(free1).To(Equal(free2 + 1)) 258 }) 259 260 It("Podman info: check for client information when no system service", func() { 261 // the output for this information is not really something we can marshall 262 want := runtime.GOOS + "/" + runtime.GOARCH 263 podmanTest.StopRemoteService() 264 SkipIfNotRemote("Specifically testing a failed remote connection") 265 info := podmanTest.Podman([]string{"info"}) 266 info.WaitWithDefaultTimeout() 267 Expect(info.OutputToString()).To(ContainSubstring(want)) 268 Expect(info).ToNot(ExitCleanly()) 269 podmanTest.StartRemoteService() // Start service again so teardown runs clean 270 }) 271 })