github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/container_test.go (about)

     1  package db_test
     2  
     3  import (
     4  	sq "github.com/Masterminds/squirrel"
     5  	"github.com/pf-qiu/concourse/v6/atc"
     6  	"github.com/pf-qiu/concourse/v6/atc/db"
     7  	. "github.com/onsi/ginkgo"
     8  	. "github.com/onsi/gomega"
     9  )
    10  
    11  var _ = Describe("Container", func() {
    12  	var (
    13  		creatingContainer db.CreatingContainer
    14  		expectedHandles   []string
    15  		build             db.Build
    16  	)
    17  
    18  	var safelyCloseConection = func() {
    19  		BeforeEach(func() {
    20  			_ = dbConn.Close()
    21  		})
    22  		AfterEach(func() {
    23  			dbConn = postgresRunner.OpenConn()
    24  		})
    25  	}
    26  
    27  	BeforeEach(func() {
    28  		var err error
    29  		build, err = defaultTeam.CreateOneOffBuild()
    30  		Expect(err).NotTo(HaveOccurred())
    31  
    32  		creatingContainer, err = defaultWorker.CreateContainer(
    33  			db.NewBuildStepContainerOwner(build.ID(), "some-plan", defaultTeam.ID()),
    34  			fullMetadata,
    35  		)
    36  		Expect(err).ToNot(HaveOccurred())
    37  	})
    38  
    39  	Describe("Metadata", func() {
    40  		It("returns the container metadata", func() {
    41  			Expect(creatingContainer.Metadata()).To(Equal(fullMetadata))
    42  		})
    43  	})
    44  
    45  	Describe("Created", func() {
    46  		Context("when the container is already created", func() {
    47  			var createdContainer db.CreatedContainer
    48  
    49  			BeforeEach(func() {
    50  				var err error
    51  				createdContainer, err = creatingContainer.Created()
    52  				Expect(err).NotTo(HaveOccurred())
    53  			})
    54  
    55  			It("returns a created container and no error", func() {
    56  				Expect(createdContainer).NotTo(BeNil())
    57  			})
    58  
    59  			Describe("Volumes", func() {
    60  				BeforeEach(func() {
    61  					creatingVolume1, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-path-1")
    62  					Expect(err).NotTo(HaveOccurred())
    63  					_, err = creatingVolume1.Created()
    64  					Expect(err).NotTo(HaveOccurred())
    65  					expectedHandles = append(expectedHandles, creatingVolume1.Handle())
    66  
    67  					creatingVolume2, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-path-2")
    68  					Expect(err).NotTo(HaveOccurred())
    69  					_, err = creatingVolume2.Created()
    70  					Expect(err).NotTo(HaveOccurred())
    71  					expectedHandles = append(expectedHandles, creatingVolume2.Handle())
    72  
    73  					createdContainer, err = creatingContainer.Created()
    74  					Expect(err).NotTo(HaveOccurred())
    75  				})
    76  
    77  				It("returns created container volumes", func() {
    78  					volumes, err := volumeRepository.FindVolumesForContainer(createdContainer)
    79  					Expect(err).NotTo(HaveOccurred())
    80  					Expect(volumes).To(HaveLen(2))
    81  					Expect([]string{volumes[0].Handle(), volumes[1].Handle()}).To(ConsistOf(expectedHandles))
    82  					Expect([]string{volumes[0].Path(), volumes[1].Path()}).To(ConsistOf("some-path-1", "some-path-2"))
    83  				})
    84  			})
    85  
    86  			Describe("Metadata", func() {
    87  				It("returns the container metadata", func() {
    88  					Expect(createdContainer.Metadata()).To(Equal(fullMetadata))
    89  				})
    90  			})
    91  		})
    92  	})
    93  
    94  	Describe("Destroying", func() {
    95  		Context("when the container is already in destroying state", func() {
    96  			var createdContainer db.CreatedContainer
    97  			var destroyingContainer db.DestroyingContainer
    98  
    99  			BeforeEach(func() {
   100  				var err error
   101  				createdContainer, err = creatingContainer.Created()
   102  				Expect(err).NotTo(HaveOccurred())
   103  
   104  				destroyingContainer, err = createdContainer.Destroying()
   105  				Expect(err).NotTo(HaveOccurred())
   106  			})
   107  
   108  			It("returns a destroying container and no error", func() {
   109  				Expect(destroyingContainer).NotTo(BeNil())
   110  			})
   111  
   112  			Describe("Metadata", func() {
   113  				It("returns the container metadata", func() {
   114  					Expect(destroyingContainer.Metadata()).To(Equal(fullMetadata))
   115  				})
   116  			})
   117  		})
   118  	})
   119  
   120  	Describe("Failed", func() {
   121  		var failedContainer db.FailedContainer
   122  		var failedErr error
   123  		var failedContainerHandles []string
   124  
   125  		Context("db conn is closed", func() {
   126  			safelyCloseConection()
   127  			It("returns an error", func() {
   128  				failedContainer, failedErr = creatingContainer.Failed()
   129  				Expect(failedContainer).To(BeNil())
   130  				Expect(failedErr).To(HaveOccurred())
   131  			})
   132  		})
   133  
   134  		Context("db conn is good", func() {
   135  			JustBeforeEach(func() {
   136  				By("transition to failed")
   137  				failedContainer, failedErr = creatingContainer.Failed()
   138  
   139  				rows, err := psql.Select("handle").
   140  					From("containers").
   141  					Where(sq.Eq{"state": atc.ContainerStateFailed}).
   142  					RunWith(dbConn).
   143  					Query()
   144  				Expect(err).NotTo(HaveOccurred())
   145  
   146  				for rows.Next() {
   147  					var handle = "handle"
   148  					columns := []interface{}{&handle}
   149  
   150  					err = rows.Scan(columns...)
   151  					Expect(err).NotTo(HaveOccurred())
   152  
   153  					failedContainerHandles = append(failedContainerHandles, handle)
   154  				}
   155  			})
   156  
   157  			BeforeEach(func() {
   158  				failedErr = nil
   159  				failedContainerHandles = []string{}
   160  			})
   161  
   162  			Context("when the container is in the creating state", func() {
   163  				It("makes the state failed", func() {
   164  					Expect(failedContainerHandles).To(HaveLen(1))
   165  					Expect(failedContainerHandles).To(ContainElement(failedContainer.Handle()))
   166  				})
   167  
   168  				It("does not return an error", func() {
   169  					Expect(failedErr).ToNot(HaveOccurred())
   170  				})
   171  			})
   172  
   173  			Context("when the container is already in failed state", func() {
   174  				BeforeEach(func() {
   175  					_, err := creatingContainer.Failed()
   176  					Expect(err).ToNot(HaveOccurred())
   177  				})
   178  
   179  				It("keeps the state failed", func() {
   180  					Expect(failedContainerHandles).To(HaveLen(1))
   181  					Expect(failedContainerHandles).To(ContainElement(failedContainer.Handle()))
   182  				})
   183  
   184  				It("does not return an error", func() {
   185  					Expect(failedErr).ToNot(HaveOccurred())
   186  				})
   187  			})
   188  
   189  			Context("when the container is actually in created state", func() {
   190  				BeforeEach(func() {
   191  					c, err := creatingContainer.Created()
   192  					Expect(err).ToNot(HaveOccurred())
   193  					Expect(c.Handle()).NotTo(BeNil())
   194  				})
   195  
   196  				It("does not mark it as failed", func() {
   197  					Expect(failedContainerHandles).To(HaveLen(0))
   198  					Expect(failedContainer).To(BeNil())
   199  				})
   200  			})
   201  
   202  			Context("when the container is actually in destroying state", func() {
   203  				BeforeEach(func() {
   204  					createdContainer, err := creatingContainer.Created()
   205  					Expect(err).ToNot(HaveOccurred())
   206  
   207  					_, err = createdContainer.Destroying()
   208  					Expect(err).ToNot(HaveOccurred())
   209  				})
   210  
   211  				It("does not mark it as failed", func() {
   212  					Expect(failedContainerHandles).To(HaveLen(0))
   213  					Expect(failedContainer).To(BeNil())
   214  				})
   215  
   216  				It("returns an error", func() {
   217  					Expect(failedErr).To(HaveOccurred())
   218  				})
   219  			})
   220  		})
   221  	})
   222  
   223  	Describe("Destroy", func() {
   224  		var destroyErr error
   225  		var destroyed bool
   226  
   227  		Context("called on a destroying container", func() {
   228  			var destroyingContainer db.DestroyingContainer
   229  			BeforeEach(func() {
   230  				createdContainer, err := creatingContainer.Created()
   231  				Expect(err).ToNot(HaveOccurred())
   232  				destroyingContainer, err = createdContainer.Destroying()
   233  				Expect(err).ToNot(HaveOccurred())
   234  			})
   235  
   236  			JustBeforeEach(func() {
   237  				destroyed, destroyErr = destroyingContainer.Destroy()
   238  			})
   239  
   240  			It("successfully removes the row from the db", func() {
   241  				Expect(destroyed).To(BeTrue())
   242  				Expect(destroyErr).ToNot(HaveOccurred())
   243  			})
   244  
   245  			Context("errors", func() {
   246  				Context("when the db connection is closed", func() {
   247  					safelyCloseConection()
   248  					It("returns an error", func() {
   249  						Expect(destroyErr).To(HaveOccurred())
   250  					})
   251  				})
   252  				Context("when the container dissapears from the db", func() {
   253  					BeforeEach(func() {
   254  						_, err := psql.Delete("containers").
   255  							Where(sq.Eq{"handle": destroyingContainer.Handle()}).
   256  							RunWith(dbConn).
   257  							Exec()
   258  						Expect(err).NotTo(HaveOccurred())
   259  					})
   260  
   261  					It("returns an error", func() {
   262  						Expect(destroyErr).To(HaveOccurred())
   263  					})
   264  				})
   265  			})
   266  		})
   267  
   268  		Context("called on a failed container", func() {
   269  			var failedContainer db.FailedContainer
   270  
   271  			BeforeEach(func() {
   272  				var err error
   273  				failedContainer, err = creatingContainer.Failed()
   274  				Expect(err).ToNot(HaveOccurred())
   275  			})
   276  
   277  			JustBeforeEach(func() {
   278  				destroyed, destroyErr = failedContainer.Destroy()
   279  			})
   280  
   281  			It("successfully removes the row from the db", func() {
   282  				Expect(destroyed).To(BeTrue())
   283  				Expect(destroyErr).ToNot(HaveOccurred())
   284  			})
   285  
   286  			Context("errors", func() {
   287  				Context("when the db connection is closed", func() {
   288  					safelyCloseConection()
   289  					It("returns an error", func() {
   290  						Expect(destroyErr).To(HaveOccurred())
   291  					})
   292  				})
   293  
   294  				Context("when the container dissapears from the db", func() {
   295  					BeforeEach(func() {
   296  						_, err := failedContainer.Destroy()
   297  						Expect(err).ToNot(HaveOccurred())
   298  					})
   299  
   300  					It("returns an error", func() {
   301  						Expect(destroyErr).To(HaveOccurred())
   302  					})
   303  				})
   304  			})
   305  		})
   306  	})
   307  })