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  })