github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/bindings/test/containers_test.go (about)

     1  package test_bindings
     2  
     3  import (
     4  	"net/http"
     5  	"strconv"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/containers/libpod/libpod/define"
    10  	"github.com/containers/libpod/pkg/bindings"
    11  	"github.com/containers/libpod/pkg/bindings/containers"
    12  	"github.com/containers/libpod/pkg/specgen"
    13  	"github.com/containers/libpod/test/utils"
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  	"github.com/onsi/gomega/gexec"
    17  )
    18  
    19  var _ = Describe("Podman containers ", func() {
    20  	var (
    21  		bt  *bindingTest
    22  		s   *gexec.Session
    23  		err error
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		bt = newBindingTest()
    28  		bt.RestoreImagesFromCache()
    29  		s = bt.startAPIService()
    30  		time.Sleep(1 * time.Second)
    31  		err := bt.NewConnection()
    32  		Expect(err).To(BeNil())
    33  	})
    34  
    35  	AfterEach(func() {
    36  		s.Kill()
    37  		bt.cleanup()
    38  	})
    39  
    40  	It("podman pause a bogus container", func() {
    41  		// Pausing bogus container should return 404
    42  		err = containers.Pause(bt.conn, "foobar")
    43  		Expect(err).ToNot(BeNil())
    44  		code, _ := bindings.CheckResponseCode(err)
    45  		Expect(code).To(BeNumerically("==", http.StatusNotFound))
    46  	})
    47  
    48  	It("podman unpause a bogus container", func() {
    49  		// Unpausing bogus container should return 404
    50  		err = containers.Unpause(bt.conn, "foobar")
    51  		Expect(err).ToNot(BeNil())
    52  		code, _ := bindings.CheckResponseCode(err)
    53  		Expect(code).To(BeNumerically("==", http.StatusNotFound))
    54  	})
    55  
    56  	It("podman pause a running container by name", func() {
    57  		// Pausing by name should work
    58  		var name = "top"
    59  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
    60  		Expect(err).To(BeNil())
    61  		err = containers.Pause(bt.conn, name)
    62  		Expect(err).To(BeNil())
    63  
    64  		// Ensure container is paused
    65  		data, err := containers.Inspect(bt.conn, name, nil)
    66  		Expect(err).To(BeNil())
    67  		Expect(data.State.Status).To(Equal("paused"))
    68  	})
    69  
    70  	It("podman pause a running container by id", func() {
    71  		// Pausing by id should work
    72  		var name = "top"
    73  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
    74  		Expect(err).To(BeNil())
    75  		err = containers.Pause(bt.conn, cid)
    76  		Expect(err).To(BeNil())
    77  
    78  		// Ensure container is paused
    79  		data, err := containers.Inspect(bt.conn, cid, nil)
    80  		Expect(err).To(BeNil())
    81  		Expect(data.State.Status).To(Equal("paused"))
    82  	})
    83  
    84  	It("podman unpause a running container by name", func() {
    85  		// Unpausing by name should work
    86  		var name = "top"
    87  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
    88  		Expect(err).To(BeNil())
    89  		err = containers.Pause(bt.conn, name)
    90  		Expect(err).To(BeNil())
    91  		err = containers.Unpause(bt.conn, name)
    92  		Expect(err).To(BeNil())
    93  
    94  		// Ensure container is unpaused
    95  		data, err := containers.Inspect(bt.conn, name, nil)
    96  		Expect(err).To(BeNil())
    97  		Expect(data.State.Status).To(Equal("running"))
    98  	})
    99  
   100  	It("podman unpause a running container by ID", func() {
   101  		// Unpausing by ID should work
   102  		var name = "top"
   103  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   104  		Expect(err).To(BeNil())
   105  		// Pause by name
   106  		err = containers.Pause(bt.conn, name)
   107  		//paused := "paused"
   108  		//_, err = containers.Wait(bt.conn, cid, &paused)
   109  		//Expect(err).To(BeNil())
   110  		err = containers.Unpause(bt.conn, name)
   111  		Expect(err).To(BeNil())
   112  
   113  		// Ensure container is unpaused
   114  		data, err := containers.Inspect(bt.conn, name, nil)
   115  		Expect(err).To(BeNil())
   116  		Expect(data.State.Status).To(Equal("running"))
   117  	})
   118  
   119  	It("podman pause a paused container by name", func() {
   120  		// Pausing a paused container by name should fail
   121  		var name = "top"
   122  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   123  		Expect(err).To(BeNil())
   124  		err = containers.Pause(bt.conn, name)
   125  		Expect(err).To(BeNil())
   126  		err = containers.Pause(bt.conn, name)
   127  		Expect(err).ToNot(BeNil())
   128  		code, _ := bindings.CheckResponseCode(err)
   129  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   130  	})
   131  
   132  	It("podman pause a paused container by id", func() {
   133  		// Pausing a paused container by id should fail
   134  		var name = "top"
   135  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   136  		Expect(err).To(BeNil())
   137  		err = containers.Pause(bt.conn, cid)
   138  		Expect(err).To(BeNil())
   139  		err = containers.Pause(bt.conn, cid)
   140  		Expect(err).ToNot(BeNil())
   141  		code, _ := bindings.CheckResponseCode(err)
   142  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   143  	})
   144  
   145  	It("podman pause a stopped container by name", func() {
   146  		// Pausing a stopped container by name should fail
   147  		var name = "top"
   148  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   149  		Expect(err).To(BeNil())
   150  		err = containers.Stop(bt.conn, name, nil)
   151  		Expect(err).To(BeNil())
   152  		err = containers.Pause(bt.conn, name)
   153  		Expect(err).ToNot(BeNil())
   154  		code, _ := bindings.CheckResponseCode(err)
   155  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   156  	})
   157  
   158  	It("podman pause a stopped container by id", func() {
   159  		// Pausing a stopped container by id should fail
   160  		var name = "top"
   161  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   162  		Expect(err).To(BeNil())
   163  		err = containers.Stop(bt.conn, cid, nil)
   164  		Expect(err).To(BeNil())
   165  		err = containers.Pause(bt.conn, cid)
   166  		Expect(err).ToNot(BeNil())
   167  		code, _ := bindings.CheckResponseCode(err)
   168  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   169  	})
   170  
   171  	It("podman remove a paused container by id without force", func() {
   172  		// Removing a paused container without force should fail
   173  		var name = "top"
   174  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   175  		Expect(err).To(BeNil())
   176  		err = containers.Pause(bt.conn, cid)
   177  		Expect(err).To(BeNil())
   178  		err = containers.Remove(bt.conn, cid, &bindings.PFalse, &bindings.PFalse)
   179  		Expect(err).ToNot(BeNil())
   180  		code, _ := bindings.CheckResponseCode(err)
   181  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   182  	})
   183  
   184  	It("podman remove a paused container by id with force", func() {
   185  		// FIXME: Skip on F31 and later
   186  		host := utils.GetHostDistributionInfo()
   187  		osVer, err := strconv.Atoi(host.Version)
   188  		Expect(err).To(BeNil())
   189  		if host.Distribution == "fedora" && osVer >= 31 {
   190  			Skip("FIXME: https://github.com/containers/libpod/issues/5325")
   191  		}
   192  
   193  		// Removing a paused container with force should work
   194  		var name = "top"
   195  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   196  		Expect(err).To(BeNil())
   197  		err = containers.Pause(bt.conn, cid)
   198  		Expect(err).To(BeNil())
   199  		err = containers.Remove(bt.conn, cid, &bindings.PTrue, &bindings.PFalse)
   200  		Expect(err).To(BeNil())
   201  	})
   202  
   203  	It("podman stop a paused container by name", func() {
   204  		// Stopping a paused container by name should fail
   205  		var name = "top"
   206  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   207  		Expect(err).To(BeNil())
   208  		err = containers.Pause(bt.conn, name)
   209  		Expect(err).To(BeNil())
   210  		err = containers.Stop(bt.conn, name, nil)
   211  		Expect(err).ToNot(BeNil())
   212  		code, _ := bindings.CheckResponseCode(err)
   213  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   214  	})
   215  
   216  	It("podman stop a paused container by id", func() {
   217  		// Stopping a paused container by id should fail
   218  		var name = "top"
   219  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   220  		Expect(err).To(BeNil())
   221  		err = containers.Pause(bt.conn, cid)
   222  		Expect(err).To(BeNil())
   223  		err = containers.Stop(bt.conn, cid, nil)
   224  		Expect(err).ToNot(BeNil())
   225  		code, _ := bindings.CheckResponseCode(err)
   226  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   227  	})
   228  
   229  	It("podman stop a running container by name", func() {
   230  		// Stopping a running container by name should work
   231  		var name = "top"
   232  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   233  		Expect(err).To(BeNil())
   234  		err = containers.Stop(bt.conn, name, nil)
   235  		Expect(err).To(BeNil())
   236  
   237  		// Ensure container is stopped
   238  		data, err := containers.Inspect(bt.conn, name, nil)
   239  		Expect(err).To(BeNil())
   240  		Expect(isStopped(data.State.Status)).To(BeTrue())
   241  	})
   242  
   243  	It("podman stop a running container by ID", func() {
   244  		// Stopping a running container by ID should work
   245  		var name = "top"
   246  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   247  		Expect(err).To(BeNil())
   248  		err = containers.Stop(bt.conn, cid, nil)
   249  		Expect(err).To(BeNil())
   250  
   251  		// Ensure container is stopped
   252  		data, err := containers.Inspect(bt.conn, name, nil)
   253  		Expect(err).To(BeNil())
   254  		Expect(isStopped(data.State.Status)).To(BeTrue())
   255  	})
   256  
   257  	It("podman wait no condition", func() {
   258  		var (
   259  			name           = "top"
   260  			exitCode int32 = -1
   261  		)
   262  		_, err := containers.Wait(bt.conn, "foobar", nil)
   263  		Expect(err).ToNot(BeNil())
   264  		code, _ := bindings.CheckResponseCode(err)
   265  		Expect(code).To(BeNumerically("==", http.StatusNotFound))
   266  
   267  		errChan := make(chan error)
   268  		_, err = bt.RunTopContainer(&name, nil, nil)
   269  		Expect(err).To(BeNil())
   270  		go func() {
   271  			exitCode, err = containers.Wait(bt.conn, name, nil)
   272  			errChan <- err
   273  			close(errChan)
   274  		}()
   275  		err = containers.Stop(bt.conn, name, nil)
   276  		Expect(err).To(BeNil())
   277  		wait := <-errChan
   278  		Expect(wait).To(BeNil())
   279  		Expect(exitCode).To(BeNumerically("==", 143))
   280  	})
   281  
   282  	It("podman wait to pause|unpause condition", func() {
   283  		var (
   284  			name           = "top"
   285  			exitCode int32 = -1
   286  			pause          = define.ContainerStatePaused
   287  			running        = define.ContainerStateRunning
   288  		)
   289  		errChan := make(chan error)
   290  		_, err := bt.RunTopContainer(&name, nil, nil)
   291  		Expect(err).To(BeNil())
   292  		go func() {
   293  			exitCode, err = containers.Wait(bt.conn, name, &pause)
   294  			errChan <- err
   295  			close(errChan)
   296  		}()
   297  		err = containers.Pause(bt.conn, name)
   298  		Expect(err).To(BeNil())
   299  		wait := <-errChan
   300  		Expect(wait).To(BeNil())
   301  		Expect(exitCode).To(BeNumerically("==", -1))
   302  
   303  		errChan = make(chan error)
   304  		go func() {
   305  			_, waitErr := containers.Wait(bt.conn, name, &running)
   306  			errChan <- waitErr
   307  			close(errChan)
   308  		}()
   309  		err = containers.Unpause(bt.conn, name)
   310  		Expect(err).To(BeNil())
   311  		unPausewait := <-errChan
   312  		Expect(unPausewait).To(BeNil())
   313  		Expect(exitCode).To(BeNumerically("==", -1))
   314  	})
   315  
   316  	It("run  healthcheck", func() {
   317  		bt.runPodman([]string{"run", "-d", "--name", "hc", "--health-interval", "disable", "--health-retries", "2", "--health-cmd", "ls / || exit 1", alpine.name, "top"})
   318  
   319  		// bogus name should result in 404
   320  		_, err := containers.RunHealthCheck(bt.conn, "foobar")
   321  		Expect(err).ToNot(BeNil())
   322  		code, _ := bindings.CheckResponseCode(err)
   323  		Expect(code).To(BeNumerically("==", http.StatusNotFound))
   324  
   325  		// a container that has no healthcheck should be a 409
   326  		var name = "top"
   327  		bt.RunTopContainer(&name, &bindings.PFalse, nil)
   328  		_, err = containers.RunHealthCheck(bt.conn, name)
   329  		Expect(err).ToNot(BeNil())
   330  		code, _ = bindings.CheckResponseCode(err)
   331  		Expect(code).To(BeNumerically("==", http.StatusConflict))
   332  
   333  		// TODO for the life of me, i cannot get this to work. maybe another set
   334  		// of eyes will
   335  		// successful healthcheck
   336  		//status := "healthy"
   337  		//for i:=0; i < 10; i++ {
   338  		//	result, err := containers.RunHealthCheck(connText, "hc")
   339  		//	Expect(err).To(BeNil())
   340  		//	if result.Status != "healthy" {
   341  		//		fmt.Println("Healthcheck container still starting, retrying in 1 second")
   342  		//		time.Sleep(1 * time.Second)
   343  		//		continue
   344  		//	}
   345  		//	status = result.Status
   346  		//	break
   347  		//}
   348  		//Expect(status).To(Equal("healthy"))
   349  
   350  		// TODO enable this when wait is working
   351  		// healthcheck on a stopped container should be a 409
   352  		//err = containers.Stop(connText, "hc", nil)
   353  		//Expect(err).To(BeNil())
   354  		//_, err = containers.Wait(connText, "hc")
   355  		//Expect(err).To(BeNil())
   356  		//_, err = containers.RunHealthCheck(connText, "hc")
   357  		//code, _ = bindings.CheckResponseCode(err)
   358  		//Expect(code).To(BeNumerically("==", http.StatusConflict))
   359  	})
   360  
   361  	It("logging", func() {
   362  		stdoutChan := make(chan string, 10)
   363  		s := specgen.NewSpecGenerator(alpine.name)
   364  		s.Terminal = true
   365  		s.Command = []string{"date", "-R"}
   366  		r, err := containers.CreateWithSpec(bt.conn, s)
   367  		Expect(err).To(BeNil())
   368  		err = containers.Start(bt.conn, r.ID, nil)
   369  		Expect(err).To(BeNil())
   370  
   371  		_, err = containers.Wait(bt.conn, r.ID, nil)
   372  		Expect(err).To(BeNil())
   373  
   374  		opts := containers.LogOptions{Stdout: &bindings.PTrue, Follow: &bindings.PTrue}
   375  		go func() {
   376  			containers.Logs(bt.conn, r.ID, opts, stdoutChan, nil)
   377  		}()
   378  		o := <-stdoutChan
   379  		o = strings.ReplaceAll(o, "\r", "")
   380  		_, err = time.Parse(time.RFC1123Z, o)
   381  		Expect(err).To(BeNil())
   382  	})
   383  
   384  	It("podman top", func() {
   385  		var name = "top"
   386  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   387  		Expect(err).To(BeNil())
   388  
   389  		// By name
   390  		_, err = containers.Top(bt.conn, name, nil)
   391  		Expect(err).To(BeNil())
   392  
   393  		// By id
   394  		_, err = containers.Top(bt.conn, cid, nil)
   395  		Expect(err).To(BeNil())
   396  
   397  		// With descriptors
   398  		output, err := containers.Top(bt.conn, cid, []string{"user,pid,hpid"})
   399  		Expect(err).To(BeNil())
   400  		header := strings.Split(output[0], "\t")
   401  		for _, d := range []string{"USER", "PID", "HPID"} {
   402  			Expect(d).To(BeElementOf(header))
   403  		}
   404  
   405  		// With bogus ID
   406  		_, err = containers.Top(bt.conn, "IdoNotExist", nil)
   407  		Expect(err).ToNot(BeNil())
   408  
   409  		// With bogus descriptors
   410  		_, err = containers.Top(bt.conn, cid, []string{"Me,Neither"})
   411  		Expect(err).To(BeNil())
   412  	})
   413  
   414  	It("podman bogus container does not exist in local storage", func() {
   415  		// Bogus container existence check should fail
   416  		containerExists, err := containers.Exists(bt.conn, "foobar")
   417  		Expect(err).To(BeNil())
   418  		Expect(containerExists).To(BeFalse())
   419  	})
   420  
   421  	It("podman container exists in local storage by name", func() {
   422  		// Container existence check by name should work
   423  		var name = "top"
   424  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   425  		Expect(err).To(BeNil())
   426  		containerExists, err := containers.Exists(bt.conn, name)
   427  		Expect(err).To(BeNil())
   428  		Expect(containerExists).To(BeTrue())
   429  	})
   430  
   431  	It("podman container exists in local storage by ID", func() {
   432  		// Container existence check by ID should work
   433  		var name = "top"
   434  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   435  		Expect(err).To(BeNil())
   436  		containerExists, err := containers.Exists(bt.conn, cid)
   437  		Expect(err).To(BeNil())
   438  		Expect(containerExists).To(BeTrue())
   439  	})
   440  
   441  	It("podman container exists in local storage by short ID", func() {
   442  		// Container existence check by short ID should work
   443  		var name = "top"
   444  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   445  		Expect(err).To(BeNil())
   446  		containerExists, err := containers.Exists(bt.conn, cid[0:12])
   447  		Expect(err).To(BeNil())
   448  		Expect(containerExists).To(BeTrue())
   449  	})
   450  
   451  	It("podman kill bogus container", func() {
   452  		// Killing bogus container should return 404
   453  		err := containers.Kill(bt.conn, "foobar", "SIGTERM")
   454  		Expect(err).ToNot(BeNil())
   455  		code, _ := bindings.CheckResponseCode(err)
   456  		Expect(code).To(BeNumerically("==", http.StatusNotFound))
   457  	})
   458  
   459  	It("podman kill a running container by name with SIGINT", func() {
   460  		// Killing a running container should work
   461  		var name = "top"
   462  		_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   463  		Expect(err).To(BeNil())
   464  		err = containers.Kill(bt.conn, name, "SIGINT")
   465  		Expect(err).To(BeNil())
   466  		_, err = containers.Exists(bt.conn, name)
   467  		Expect(err).To(BeNil())
   468  	})
   469  
   470  	It("podman kill a running container by ID with SIGTERM", func() {
   471  		// Killing a running container by ID should work
   472  		var name = "top"
   473  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   474  		Expect(err).To(BeNil())
   475  		err = containers.Kill(bt.conn, cid, "SIGTERM")
   476  		Expect(err).To(BeNil())
   477  		_, err = containers.Exists(bt.conn, cid)
   478  		Expect(err).To(BeNil())
   479  	})
   480  
   481  	It("podman kill a running container by ID with SIGKILL", func() {
   482  		// Killing a running container by ID with TERM should work
   483  		var name = "top"
   484  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   485  		Expect(err).To(BeNil())
   486  		err = containers.Kill(bt.conn, cid, "SIGKILL")
   487  		Expect(err).To(BeNil())
   488  	})
   489  
   490  	It("podman kill a running container by bogus signal", func() {
   491  		//Killing a running container by bogus signal should fail
   492  		var name = "top"
   493  		cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
   494  		Expect(err).To(BeNil())
   495  		err = containers.Kill(bt.conn, cid, "foobar")
   496  		Expect(err).ToNot(BeNil())
   497  		code, _ := bindings.CheckResponseCode(err)
   498  		Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
   499  	})
   500  
   501  	It("podman kill latest container with SIGTERM", func() {
   502  		// Killing latest container should work
   503  		var name1 = "first"
   504  		var name2 = "second"
   505  		var latestContainers = 1
   506  		_, err := bt.RunTopContainer(&name1, &bindings.PFalse, nil)
   507  		Expect(err).To(BeNil())
   508  		_, err = bt.RunTopContainer(&name2, &bindings.PFalse, nil)
   509  		Expect(err).To(BeNil())
   510  		containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil, nil)
   511  		Expect(err).To(BeNil())
   512  		err = containers.Kill(bt.conn, containerLatestList[0].Names[0], "SIGTERM")
   513  		Expect(err).To(BeNil())
   514  	})
   515  
   516  	It("container init on a bogus container", func() {
   517  		err := containers.ContainerInit(bt.conn, "doesnotexist")
   518  		Expect(err).ToNot(BeNil())
   519  		code, _ := bindings.CheckResponseCode(err)
   520  		Expect(code).To(BeNumerically("==", http.StatusNotFound))
   521  	})
   522  
   523  	It("container init", func() {
   524  		s := specgen.NewSpecGenerator(alpine.name)
   525  		ctr, err := containers.CreateWithSpec(bt.conn, s)
   526  		Expect(err).To(BeNil())
   527  		err = containers.ContainerInit(bt.conn, ctr.ID)
   528  		Expect(err).To(BeNil())
   529  		//	trying to init again should be an error
   530  		err = containers.ContainerInit(bt.conn, ctr.ID)
   531  		Expect(err).ToNot(BeNil())
   532  	})
   533  
   534  })