func init() {
	Describe("concreteCompiler", func() {
		var (
			compiler       Compiler
			compressor     *fakecmd.FakeCompressor
			blobstore      *fakeblobstore.FakeBlobstore
			fs             *fakesys.FakeFileSystem
			runner         *fakecmdrunner.FakeFileLoggingCmdRunner
			packageApplier *fakepackages.FakeApplier
			packagesBc     *fakebc.FakeBundleCollection
		)

		BeforeEach(func() {
			compressor = fakecmd.NewFakeCompressor()
			blobstore = &fakeblobstore.FakeBlobstore{}
			fs = fakesys.NewFakeFileSystem()
			runner = fakecmdrunner.NewFakeFileLoggingCmdRunner()
			packageApplier = fakepackages.NewFakeApplier()
			packagesBc = fakebc.NewFakeBundleCollection()

			compiler = NewConcreteCompiler(
				compressor,
				blobstore,
				fs,
				runner,
				FakeCompileDirProvider{Dir: "/fake-compile-dir"},
				packageApplier,
				packagesBc,
			)
		})

		BeforeEach(func() {
			fs.MkdirAll("/fake-compile-dir", os.ModePerm)
		})

		Describe("Compile", func() {
			var (
				bundle  *fakebc.FakeBundle
				pkg     Package
				pkgDeps []boshmodels.Package
			)

			BeforeEach(func() {
				bundle = packagesBc.FakeGet(boshmodels.Package{
					Name:    "pkg_name",
					Version: "pkg_version",
				})

				bundle.InstallPath = "/fake-dir/data/packages/pkg_name/pkg_version"
				bundle.EnablePath = "/fake-dir/packages/pkg_name"

				compressor.CompressFilesInDirTarballPath = "/tmp/compressed-compiled-package"

				pkg, pkgDeps = getCompileArgs()
			})

			It("returns blob id and sha1 of created compiled package", func() {
				blobstore.CreateBlobID = "fake-blob-id"
				blobstore.CreateFingerprint = "fake-blob-sha1"

				blobID, sha1, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())

				Expect(blobID).To(Equal("fake-blob-id"))
				Expect(sha1).To(Equal("fake-blob-sha1"))
			})

			It("cleans up all packages before and after applying dependent packages", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())
				Expect(packageApplier.ActionsCalled).To(Equal([]string{"KeepOnly", "Apply", "Apply", "KeepOnly"}))
				Expect(packageApplier.KeptOnlyPackages).To(BeEmpty())
			})

			It("returns an error if cleaning up packages fails", func() {
				packageApplier.KeepOnlyErr = errors.New("fake-keep-only-error")

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("fake-keep-only-error"))
			})

			It("fetches source package from blobstore without checking SHA1 by default because of Director bug", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())

				Expect(blobstore.GetBlobIDs[0]).To(Equal("blobstore_id"))
				Expect(blobstore.GetFingerprints[0]).To(Equal(""))
			})

			PIt("(Pending Tracker Story: <https://www.pivotaltracker.com/story/show/94524232>) fetches source package from blobstore and checks SHA1 by default in future", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())

				Expect(blobstore.GetBlobIDs[0]).To(Equal("blobstore_id"))
				Expect(blobstore.GetFingerprints[0]).To(Equal("sha1"))
			})

			It("returns an error if removing compile target directory during uncompression fails", func() {
				fs.RemoveAllStub = func(path string) error {
					if path == "/fake-compile-dir/pkg_name" {
						return errors.New("fake-remove-error")
					}
					return nil
				}

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("fake-remove-error"))
			})

			It("returns an error if creating compile target directory during uncompression fails", func() {
				fs.RemoveAllStub = func(path string) error {
					if path == "/fake-compile-dir/pkg_name" {
						return errors.New("fake-mkdir-error")
					}
					return nil
				}

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("fake-mkdir-error"))
			})

			It("returns an error if removing temporary compile target directory during uncompression fails", func() {
				fs.RemoveAllStub = func(path string) error {
					if path == "/fake-compile-dir/pkg_name-bosh-agent-unpack" {
						return errors.New("fake-remove-error")
					}
					return nil
				}

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("fake-remove-error"))
			})

			It("returns an error if creating temporary compile target directory during uncompression fails", func() {
				fs.RegisterMkdirAllError("/fake-compile-dir/pkg_name-bosh-agent-unpack", errors.New("fake-mkdir-error"))

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("fake-mkdir-error"))
			})

			It("returns an error if target directory is empty during uncompression", func() {
				pkg.BlobstoreID = ""

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("Blobstore ID for package '%s' is empty", pkg.Name))
			})

			It("installs dependent packages", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())
				Expect(packageApplier.AppliedPackages).To(Equal(pkgDeps))
			})

			It("cleans up the compile directory", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())
				Expect(fs.FileExists("/fake-compile-dir/pkg_name")).To(BeFalse())
			})

			It("installs, enables and later cleans up bundle", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())
				Expect(bundle.ActionsCalled).To(Equal([]string{
					"InstallWithoutContents",
					"Enable",
					"Disable",
					"Uninstall",
				}))
			})

			It("returns an error if removing the compile directory fails", func() {
				callCount := 0
				fs.RemoveAllStub = func(path string) error {
					if path == "/fake-compile-dir/pkg_name" {
						callCount++
						if callCount > 1 {
							return errors.New("fake-remove-error")
						}
					}
					return nil
				}

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("fake-remove-error"))
			})

			Context("when packaging script exists", func() {
				const packagingScriptContents = "hi"
				BeforeEach(func() {
					compressor.DecompressFileToDirCallBack = func() {
						filename := "/fake-compile-dir/pkg_name/" + PackagingScriptName
						fs.WriteFileString(filename, packagingScriptContents)
					}
				})

				It("runs packaging script ", func() {
					_, _, err := compiler.Compile(pkg, pkgDeps)
					Expect(err).ToNot(HaveOccurred())

					expectedCmd := boshsys.Command{
						Env: map[string]string{
							"BOSH_COMPILE_TARGET":  "/fake-compile-dir/pkg_name",
							"BOSH_INSTALL_TARGET":  "/fake-dir/packages/pkg_name",
							"BOSH_PACKAGE_NAME":    "pkg_name",
							"BOSH_PACKAGE_VERSION": "pkg_version",
						},
						WorkingDir: "/fake-compile-dir/pkg_name",
					}

					cmd := runner.RunCommands[0]
					if runtime.GOOS == "windows" {
						expectedCmd.Name = "powershell"
						expectedCmd.Args = []string{"-command", fmt.Sprintf(`"iex (get-content -raw %s)"`, PackagingScriptName)}
					} else {
						expectedCmd.Name = "bash"
						expectedCmd.Args = []string{"-x", PackagingScriptName}
					}

					Expect(cmd).To(Equal(expectedCmd))
					Expect(len(runner.RunCommands)).To(Equal(1))
					Expect(runner.RunCommandJobName).To(Equal("compilation"))
					Expect(runner.RunCommandTaskName).To(Equal(PackagingScriptName))
				})

				It("propagates the error from packaging script", func() {
					runner.RunCommandErr = errors.New("fake-packaging-error")

					_, _, err := compiler.Compile(pkg, pkgDeps)
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("fake-packaging-error"))
				})
			})

			It("does not run packaging script when script does not exist", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())
				Expect(runner.RunCommands).To(BeEmpty())
			})

			It("compresses compiled package", func() {
				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())

				// archive was downloaded from the blobstore and decompress to this temp dir
				Expect(compressor.DecompressFileToDirDirs[0]).To(Equal("/fake-compile-dir/pkg_name-bosh-agent-unpack"))
				Expect(compressor.DecompressFileToDirTarballPaths[0]).To(Equal(blobstore.GetFileName))

				// contents were moved from the temp dir to the install/enable dir
				Expect(fs.RenameOldPaths[0]).To(Equal("/fake-compile-dir/pkg_name-bosh-agent-unpack"))
				Expect(fs.RenameNewPaths[0]).To(Equal("/fake-compile-dir/pkg_name"))

				// install path, presumably with your packaged code, was compressed
				installPath := "/fake-dir/data/packages/pkg_name/pkg_version"
				Expect(compressor.CompressFilesInDirDir).To(Equal(installPath))
			})

			It("uploads compressed package to blobstore", func() {
				compressor.CompressFilesInDirTarballPath = "/tmp/compressed-compiled-package"

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())
				Expect(blobstore.CreateFileNames[0]).To(Equal("/tmp/compressed-compiled-package"))
			})

			It("returs error if uploading compressed package fails", func() {
				blobstore.CreateErr = errors.New("fake-create-err")

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("fake-create-err"))
			})

			It("cleans up compressed package after uploading it to blobstore", func() {
				var beforeCleanUpTarballPath, afterCleanUpTarballPath string

				blobstore.CreateCallBack = func() {
					beforeCleanUpTarballPath = compressor.CleanUpTarballPath
				}

				_, _, err := compiler.Compile(pkg, pkgDeps)
				Expect(err).ToNot(HaveOccurred())

				// Compressed package is not cleaned up before blobstore upload
				Expect(beforeCleanUpTarballPath).To(Equal(""))

				// Deleted after it was uploaded
				afterCleanUpTarballPath = compressor.CleanUpTarballPath
				Expect(afterCleanUpTarballPath).To(Equal("/tmp/compressed-compiled-package"))
			})
		})
	})
}
Esempio n. 2
0
			dep1 = bistatepkg.CompiledPackageRecord{
				BlobID:   "fake-dependency-blobstore-id-1",
				BlobSHA1: "fake-dependency-sha1-1",
			}
			mockCompiledPackageRepo.EXPECT().Find(*dependency1).Return(dep1, true, nil).AnyTimes()

			dep2 = bistatepkg.CompiledPackageRecord{
				BlobID:   "fake-dependency-blobstore-id-2",
				BlobSHA1: "fake-dependency-sha1-2",
			}
			mockCompiledPackageRepo.EXPECT().Find(*dependency2).Return(dep2, true, nil).AnyTimes()

			// packaging file created when source is extracted
			fs.WriteFileString(path.Join(pkg.ExtractedPath, "packaging"), "")

			compressor.CompressFilesInDirTarballPath = compiledPackageTarballPath

			record := bistatepkg.CompiledPackageRecord{
				BlobID:   "fake-blob-id",
				BlobSHA1: "fake-fingerprint",
			}
			expectSave = mockCompiledPackageRepo.EXPECT().Save(*pkg, record).AnyTimes()
		})

		Context("when the compiled package repo already has the package", func() {
			JustBeforeEach(func() {
				compiledPkgRecord := bistatepkg.CompiledPackageRecord{
					BlobSHA1: "fake-fingerprint",
				}
				expectFind.Return(compiledPkgRecord, true, nil).Times(1)
			})
			It("calculates the fingerprint of the rendered", func() {
				fakeFS.TempDirDir = "fake-rendered-job-list-path"

				fakeSHA1Calculator.SetCalculateBehavior(map[string]fakebicrypto.CalculateInput{
					"fake-rendered-job-list-path": fakebicrypto.CalculateInput{Sha1: "fake-sha1"},
				})

				archive, err := renderedJobListCompressor.Compress(renderedJobList)
				Expect(err).ToNot(HaveOccurred())

				Expect(archive.Fingerprint()).To(Equal("fake-sha1"))
			})

			It("calculates the SHA1 of the archive", func() {
				fakeCompressor.CompressFilesInDirTarballPath = "fake-archive-path"

				fakeSHA1Calculator.SetCalculateBehavior(map[string]fakebicrypto.CalculateInput{
					"fake-archive-path": fakebicrypto.CalculateInput{Sha1: "fake-sha1"},
				})

				archive, err := renderedJobListCompressor.Compress(renderedJobList)
				Expect(err).ToNot(HaveOccurred())

				Expect(archive.SHA1()).To(Equal("fake-sha1"))
			})

			It("deletes the temp dir compressed into the archive", func() {
				fakeFS.TempDirDir = "fake-rendered-job-list-path"
				err := fakeFS.MkdirAll("fake-rendered-job-list-path", os.ModePerm)
				Expect(err).ToNot(HaveOccurred())
Esempio n. 4
0
		copier = fakecmd.NewFakeCopier()
		action = NewFetchLogs(compressor, copier, blobstore, dirProvider)
	})

	It("logs should be asynchronous", func() {
		Expect(action.IsAsynchronous()).To(BeTrue())
	})

	It("is not persistent", func() {
		Expect(action.IsPersistent()).To(BeFalse())
	})

	Describe("Run", func() {
		testLogs := func(logType string, filters []string, expectedFilters []string) {
			copier.FilteredCopyToTempTempDir = "/fake-temp-dir"
			compressor.CompressFilesInDirTarballPath = "logs_test.tar"
			blobstore.CreateBlobID = "my-blob-id"

			logs, err := action.Run(logType, filters)
			Expect(err).ToNot(HaveOccurred())

			var expectedPath string
			switch logType {
			case "job":
				expectedPath = path.Join("/fake", "dir", "sys", "log")
			case "agent":
				expectedPath = path.Join("/fake", "dir", "bosh", "log")
			}

			Expect(copier.FilteredCopyToTempDir).To(Equal(expectedPath))
			Expect(copier.FilteredCopyToTempFilters).To(Equal(expectedFilters))
Esempio n. 5
0
		releaseJobs := []bireljob.Job{releaseJob}

		releaseJobProperties := map[string]*biproperty.Map{}
		jobProperties := biproperty.Map{
			"fake-installation-property": "fake-installation-property-value",
		}
		globalProperties := biproperty.Map{}
		deploymentName := "fake-installation-name"
		address := ""

		renderedJobList = bitemplate.NewRenderedJobList()
		renderedJobList.Add(bitemplate.NewRenderedJob(releaseJob, "/fake-rendered-job-cpi", fakeFS, logger))

		mockJobListRenderer.EXPECT().Render(releaseJobs, releaseJobProperties, jobProperties, globalProperties, deploymentName, address).Return(renderedJobList, nil).AnyTimes()

		fakeCompressor.CompressFilesInDirTarballPath = "/fake-rendered-job-tarball-cpi.tgz"

		fakeBlobstore.CreateBlobIDs = []string{"fake-rendered-job-tarball-blobstore-id-cpi"}
		fakeBlobstore.CreateFingerprints = []string{"fake-rendered-job-tarball-sha1-cpi"}
	})

	Describe("RenderAndUploadFrom", func() {
		It("logs compile & render stages", func() {
			_, err := renderer.RenderAndUploadFrom(manifest, releaseJobs, fakeStage)
			Expect(err).ToNot(HaveOccurred())

			Expect(fakeStage.PerformCalls).To(Equal([]*fakebiui.PerformCall{
				// compile stages not produced by mockDependencyCompiler
				{Name: "Rendering job templates"},
			}))
		})