gomock.InOrder( expectCPIExtractRelease.Times(1), expectCPIInstall.Times(1), expectNewCloud.Times(1), ) err := newDeploymentDeleter().DeleteDeployment(fakeStage) Expect(err).NotTo(HaveOccurred()) }) It("deletes the extracted CPI release", func() { expectDeleteAndCleanup(true) err := newDeploymentDeleter().DeleteDeployment(fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fs.FileExists("fake-cpi-extracted-dir")).To(BeFalse()) }) It("deletes the deployment & cleans up orphans", func() { expectDeleteAndCleanup(true) err := newDeploymentDeleter().DeleteDeployment(fakeStage) Expect(err).ToNot(HaveOccurred()) Expect(fakeUI.Errors).To(BeEmpty()) }) It("deletes the local CPI installation", func() { expectDeleteAndCleanup(false) mockCpiUninstaller.EXPECT().Uninstall(gomock.Any()).Return(nil) err := newDeploymentDeleter().DeleteDeployment(fakeStage)
It("returns the repo record", func() { record, _, err := compiler.Compile(pkg) Expect(err).ToNot(HaveOccurred()) Expect(record).To(Equal(bistatepkg.CompiledPackageRecord{ BlobID: "fake-blob-id", BlobSHA1: "fake-fingerprint", })) }) It("cleans up the packages dir", func() { _, _, err := compiler.Compile(pkg) Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(packagesDir)).To(BeFalse()) }) Context("when dependency installation fails", func() { JustBeforeEach(func() { fakeExtractor.ExtractReturns(errors.New("fake-install-error")) }) It("returns an error", func() { _, _, err := compiler.Compile(pkg) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-install-error")) }) }) Context("when the packaging script does not exist", func() {
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")) }) }) }) }
err := monit.Start() Expect(err).ToNot(HaveOccurred()) Expect(client.ServicesInGroupName).To(Equal("vcap")) Expect(len(client.StartServiceNames)).To(Equal(1)) Expect(client.StartServiceNames[0]).To(Equal("fake-service")) }) It("deletes stopped file", func() { fs.MkdirAll("/var/vcap/monit/stopped", os.FileMode(0755)) fs.WriteFileString("/var/vcap/monit/stopped", "") err := monit.Start() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists("/var/vcap/monit/stopped")).ToNot(BeTrue()) }) It("does not fail if stopped file is not present", func() { err := monit.Start() Expect(err).ToNot(HaveOccurred()) }) }) Describe("Stop", func() { It("stop stops each monit service in group vcap", func() { client.ServicesInGroupServices = []string{"fake-service"} err := monit.Stop() Expect(err).ToNot(HaveOccurred())
_, err := provider.Get(source, fakeStage) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("'fake-sha2' does not match expected SHA1 'fake-sha1'")) }) It("retries downloading up to 3 times", func() { _, err := provider.Get(source, fakeStage) Expect(err).To(HaveOccurred()) Expect(httpClient.GetInputs).To(HaveLen(3)) }) It("removes the downloaded file", func() { _, err := provider.Get(source, fakeStage) Expect(err).To(HaveOccurred()) Expect(fs.FileExists(tempDownloadFilePath)).To(BeFalse()) }) }) Context("when saving to cache fails", func() { BeforeEach(func() { // Creating cache base directory fails fs.MkdirAllError = errors.New("fake-mkdir-error") }) It("returns an error", func() { _, err := provider.Get(source, fakeStage) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-mkdir-error")) })
PackageNames: []string{ "fake-release-package-name", }, Packages: []*birelpkg.Package{expectedPackage}, Properties: map[string]bireljob.PropertyDefinition{}, }, }, []*birelpkg.Package{expectedPackage}, "/extracted-release-path", fakeFS, false, ) Expect(release).To(Equal(expectedRelease)) Expect(fakeFS.FileExists("/extracted-release-path")).To(BeTrue()) Expect(fakeFS.FileExists("/extracted-release-path/extracted_packages/fake-release-package-name")).To(BeTrue()) Expect(fakeFS.FileExists("/extracted-release-path/extracted_jobs/cpi")).To(BeTrue()) }) }) Context("and the tarball is not a valid BOSH release", func() { BeforeEach(func() { fakeFS.WriteFileString("/extracted-release-path/release.MF", `{}`) fakeReleaseValidator.ValidateError = bosherr.Error("fake-error") }) It("returns an error", func() { _, err := releaseExtractor.Extract(releaseTarballPath) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-error"))
}) It("returns error when it fails to change permissions", func() { fs.ChmodErr = errors.New("fake-chmod-error") _, _, err := fileBundle.Install(sourcePath) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-chmod-error")) }) It("does not install bundle if it fails to change permissions", func() { fs.ChmodErr = errors.New("fake-chmod-error") _, _, err := fileBundle.Install(sourcePath) Expect(err).To(HaveOccurred()) Expect(fs.FileExists(installPath)).To(BeFalse()) }) }) Describe("InstallWithoutContents", func() { It("installs the bundle at the given path with the correct permissions", func() { actualFs, path, err := fileBundle.InstallWithoutContents() Expect(err).NotTo(HaveOccurred()) Expect(actualFs).To(Equal(fs)) Expect(path).To(Equal(installPath)) fileStats := fs.GetFileTestStat(installPath) Expect(fileStats).ToNot(BeNil()) Expect(fileStats.FileType).To(Equal(fakesys.FakeFileType(fakesys.FakeFileTypeDir))) Expect(fileStats.FileMode).To(Equal(os.FileMode(0755))) })
It("extracts and parses the stemcell manifest", func() { stemcell, err := extractor.Extract(stemcellTarballPath) Expect(err).ToNot(HaveOccurred()) Expect(stemcell).To(Equal(expectedExtractedStemcell)) Expect(reader.ReadInputs).To(Equal([]fakebistemcell.ReadInput{ { StemcellTarballPath: stemcellTarballPath, DestPath: stemcellExtractionDir, }, })) }) It("does not delete the destination file path", func() { extractor.Extract(stemcellTarballPath) Expect(fs.FileExists(stemcellExtractionDir)).To(BeTrue()) }) }) Context("when the read fails", func() { BeforeEach(func() { reader.SetReadBehavior(stemcellTarballPath, stemcellExtractionDir, expectedExtractedStemcell, errors.New("fake-read-error")) }) It("returns an error", func() { _, err := extractor.Extract(stemcellTarballPath) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-read-error")) }) It("deletes the destination file path", func() {
Context("when the job does not exist", func() { It("returns nil and false", func() { _, ok := release.FindJobByName("fake-non-existent-job") Expect(ok).To(BeFalse()) }) }) }) Describe("Delete", func() { BeforeEach(func() { fakeFS.WriteFileString("fake-extracted-path", "") }) It("deletes the extracted release path", func() { Expect(fakeFS.FileExists("fake-extracted-path")).To(BeTrue()) err := release.Delete() Expect(err).ToNot(HaveOccurred()) Expect(fakeFS.FileExists("fake-extracted-path")).To(BeFalse()) }) }) Describe("Exists", func() { BeforeEach(func() { fakeFS.WriteFileString("fake-extracted-path", "") }) It("returns false after deletion", func() { Expect(release.Exists()).To(BeTrue()) err := release.Delete() Expect(err).ToNot(HaveOccurred())
err := fs.RemoveAll(deploymentStatePath) Expect(err).ToNot(HaveOccurred()) directorID = "fake-uuid-1" }) It("creates one", func() { expectDeployFlow() // new directorID will be generated mockAgentClientFactory.EXPECT().NewAgentClient(gomock.Any(), mbusURL).Return(mockAgentClient) err := newDeployCmd().Run(fakeStage, []string{deploymentManifestPath}) Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(deploymentStatePath)).To(BeTrue()) deploymentState, err := deploymentStateService.Load() Expect(err).ToNot(HaveOccurred()) Expect(deploymentState.DirectorID).To(Equal(directorID)) }) }) Context("when the deployment has been deployed", func() { JustBeforeEach(func() { expectDeployFlow() err := newDeployCmd().Run(fakeStage, []string{deploymentManifestPath}) Expect(err).ToNot(HaveOccurred()) })
It("deletes the rendered jobs", func() { err := fs.MkdirAll("fake-path-0", os.ModePerm) Expect(err).ToNot(HaveOccurred()) err = fs.MkdirAll("fake-path-1", os.ModePerm) Expect(err).ToNot(HaveOccurred()) renderedJob0 := NewRenderedJob(bireljob.Job{Name: "fake-job-0"}, "fake-path-0", fs, logger) renderedJob1 := NewRenderedJob(bireljob.Job{Name: "fake-job-1"}, "fake-path-1", fs, logger) renderedJobList.Add(renderedJob0) renderedJobList.Add(renderedJob1) err = renderedJobList.Delete() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists("fake-path-0")).To(BeFalse()) Expect(fs.FileExists("fake-path-1")).To(BeFalse()) }) Context("when deleting from the file system fails", func() { JustBeforeEach(func() { fs.RemoveAllStub = func(_ string) error { return bosherr.Error("fake-delete-error") } }) It("returns an error", func() { renderedJob0 := NewRenderedJob(bireljob.Job{Name: "fake-job-0"}, "fake-path-0", fs, logger) renderedJobList.Add(renderedJob0) err := renderedJobList.Delete()
func init() { Describe("renderedJobApplier", func() { var ( jobsBc *fakebc.FakeBundleCollection jobSupervisor *fakejobsuper.FakeJobSupervisor packageApplierProvider *fakepackages.FakeApplierProvider blobstore *fakeblob.FakeBlobstore compressor *fakecmd.FakeCompressor fs *fakesys.FakeFileSystem applier Applier ) BeforeEach(func() { jobsBc = fakebc.NewFakeBundleCollection() jobSupervisor = fakejobsuper.NewFakeJobSupervisor() packageApplierProvider = fakepackages.NewFakeApplierProvider() blobstore = fakeblob.NewFakeBlobstore() fs = fakesys.NewFakeFileSystem() compressor = fakecmd.NewFakeCompressor() logger := boshlog.NewLogger(boshlog.LevelNone) applier = NewRenderedJobApplier( jobsBc, jobSupervisor, packageApplierProvider, blobstore, compressor, fs, logger, ) }) Describe("Prepare & Apply", func() { var ( job models.Job bundle *fakebc.FakeBundle ) BeforeEach(func() { job, bundle = buildJob(jobsBc) }) ItInstallsJob := func(act func() error) { BeforeEach(func() { fs.TempDirDir = "/fake-tmp-dir" }) It("returns error when installing job fails", func() { bundle.InstallError = errors.New("fake-install-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-install-error")) }) It("downloads and later cleans up downloaded job template blob", func() { blobstore.GetFileName = "/fake-blobstore-file-name" err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs[0]).To(Equal("fake-blobstore-id")) Expect(blobstore.GetFingerprints[0]).To(Equal(boshcrypto.NewDigest("sha1", "fake-blob-sha1"))) // downloaded file is cleaned up Expect(blobstore.CleanUpFileName).To(Equal("/fake-blobstore-file-name")) }) It("returns error when downloading job template blob fails", func() { blobstore.GetError = errors.New("fake-get-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-error")) }) It("decompresses job template blob to tmp path and later cleans it up", func() { blobstore.GetFileName = "/fake-blobstore-file-name" var tmpDirExistsBeforeInstall bool bundle.InstallCallBack = func() { tmpDirExistsBeforeInstall = true } err := act() Expect(err).ToNot(HaveOccurred()) Expect(compressor.DecompressFileToDirTarballPaths[0]).To(Equal("/fake-blobstore-file-name")) Expect(compressor.DecompressFileToDirDirs[0]).To(Equal("/fake-tmp-dir")) // tmp dir exists before bundle install Expect(tmpDirExistsBeforeInstall).To(BeTrue()) // tmp dir is cleaned up after install Expect(fs.FileExists(fs.TempDirDir)).To(BeFalse()) }) It("returns error when temporary directory creation fails", func() { fs.TempDirError = errors.New("fake-filesystem-tempdir-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-filesystem-tempdir-error")) }) It("can process sha1 checksums in the new format", func() { blobstore.GetFileName = "/fake-blobstore-file-name" job.Source.Sha1 = "sha1:fake-blob-sha1" err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs[0]).To(Equal("fake-blobstore-id")) Expect(blobstore.GetFingerprints[0]).To(Equal(boshcrypto.NewDigest("sha1", "fake-blob-sha1"))) }) It("can process sha2 checksums", func() { blobstore.GetFileName = "/fake-blobstore-file-name" job.Source.Sha1 = "sha256:fake-blob-sha256" err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs[0]).To(Equal("fake-blobstore-id")) Expect(blobstore.GetFingerprints[0]).To(Equal(boshcrypto.NewDigest("sha256", "fake-blob-sha256"))) }) It("returns error when given and unsupported fingerprint", func() { blobstore.GetFileName = "/fake-blobstore-file-name" job.Source.Sha1 = "unsupported:checksum" err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Parsing job blob digest")) }) It("returns error when decompressing job template fails", func() { compressor.DecompressFileToDirErr = errors.New("fake-decompress-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-decompress-error")) }) It("returns error when walking the tree of files fails", func() { fs.WalkErr = errors.New("fake-walk-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-walk-error")) }) It("installs bundle from decompressed tmp path of a job template", func() { var installedBeforeDecompression bool compressor.DecompressFileToDirCallBack = func() { installedBeforeDecompression = bundle.Installed } err := act() Expect(err).ToNot(HaveOccurred()) // bundle installation did not happen before decompression Expect(installedBeforeDecompression).To(BeFalse()) // make sure that bundle install happened after decompression Expect(bundle.InstallSourcePath).To(Equal("/fake-tmp-dir/fake-path-in-archive")) }) It("sets executable bit for the bin and config directories", func() { var binDirStats, configDirStats *fakesys.FakeFileStats compressor.DecompressFileToDirCallBack = func() { fs.WriteFile("/fake-tmp-dir/fake-path-in-archive/bin/blarg", []byte{}) fs.WriteFile("/fake-tmp-dir/fake-path-in-archive/config/blarg.yml", []byte{}) } bundle.InstallCallBack = func() { binDirStats = fs.GetFileTestStat("/fake-tmp-dir/fake-path-in-archive/bin") configDirStats = fs.GetFileTestStat("/fake-tmp-dir/fake-path-in-archive/config") } err := act() Expect(err).ToNot(HaveOccurred()) Expect(int(binDirStats.FileMode)).To(Equal(0755)) Expect(int(configDirStats.FileMode)).To(Equal(0755)) }) It("sets executable bit for files in bin", func() { compressor.DecompressFileToDirCallBack = func() { fs.WriteFile("/fake-tmp-dir/fake-path-in-archive/bin/test1", []byte{}) fs.WriteFile("/fake-tmp-dir/fake-path-in-archive/bin/test2", []byte{}) fs.WriteFile("/fake-tmp-dir/fake-path-in-archive/config/test", []byte{}) } fs.SetGlob("/fake-tmp-dir/fake-path-in-archive/bin/*", []string{ "/fake-tmp-dir/fake-path-in-archive/bin/test1", "/fake-tmp-dir/fake-path-in-archive/bin/test2", }) var binTest1Stats, binTest2Stats, configTestStats *fakesys.FakeFileStats bundle.InstallCallBack = func() { binTest1Stats = fs.GetFileTestStat("/fake-tmp-dir/fake-path-in-archive/bin/test1") binTest2Stats = fs.GetFileTestStat("/fake-tmp-dir/fake-path-in-archive/bin/test2") configTestStats = fs.GetFileTestStat("/fake-tmp-dir/fake-path-in-archive/config/test") } err := act() Expect(err).ToNot(HaveOccurred()) // bin files are executable Expect(int(binTest1Stats.FileMode)).To(Equal(0755)) Expect(int(binTest2Stats.FileMode)).To(Equal(0755)) // non-bin files are not made executable Expect(int(configTestStats.FileMode)).ToNot(Equal(0755)) }) It("sets 644 permissions for files in config", func() { compressor.DecompressFileToDirCallBack = func() { fs.WriteFile("/fake-tmp-dir/fake-path-in-archive/config/config1", []byte{}) fs.WriteFile("/fake-tmp-dir/fake-path-in-archive/config/config2", []byte{}) } fs.SetGlob("/fake-tmp-dir/fake-path-in-archive/config/*", []string{ "/fake-tmp-dir/fake-path-in-archive/config/config1", "/fake-tmp-dir/fake-path-in-archive/config/config2", }) var config1Stats, config2Stats *fakesys.FakeFileStats bundle.InstallCallBack = func() { config1Stats = fs.GetFileTestStat("/fake-tmp-dir/fake-path-in-archive/config/config1") config2Stats = fs.GetFileTestStat("/fake-tmp-dir/fake-path-in-archive/config/config2") } err := act() Expect(err).ToNot(HaveOccurred()) // permission for config files should be readable by all Expect(int(config1Stats.FileMode)).To(Equal(0644)) Expect(int(config2Stats.FileMode)).To(Equal(0644)) }) } ItUpdatesPackages := func(act func() error) { var packageApplier *fakepackages.FakeApplier BeforeEach(func() { packageApplier = fakepackages.NewFakeApplier() packageApplierProvider.JobSpecificAppliers[job.Name] = packageApplier }) It("applies each package that job depends on and then cleans up packages", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(packageApplier.ActionsCalled).To(Equal([]string{"Apply", "Apply", "KeepOnly"})) Expect(len(packageApplier.AppliedPackages)).To(Equal(2)) // present Expect(packageApplier.AppliedPackages).To(Equal(job.Packages)) }) It("returns error when applying package that job depends on fails", func() { packageApplier.ApplyError = errors.New("fake-apply-err") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-apply-err")) }) It("keeps only currently required packages but does not completely uninstall them", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(len(packageApplier.KeptOnlyPackages)).To(Equal(2)) // present Expect(packageApplier.KeptOnlyPackages).To(Equal(job.Packages)) }) It("returns error when keeping only currently required packages fails", func() { packageApplier.KeepOnlyErr = errors.New("fake-keep-only-err") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-keep-only-err")) }) } Describe("Prepare", func() { act := func() error { return applier.Prepare(job) } It("return an error if getting file bundle fails", func() { jobsBc.GetErr = errors.New("fake-get-bundle-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-bundle-error")) }) It("returns an error if checking for installed path fails", func() { bundle.IsInstalledErr = errors.New("fake-is-installed-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-is-installed-error")) }) Context("when job is already installed", func() { BeforeEach(func() { bundle.Installed = true }) It("does not install", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{})) // no Install }) It("does not download the job template", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs).To(BeNil()) }) }) Context("when job is not installed", func() { BeforeEach(func() { bundle.Installed = false }) It("installs job (but does not enable)", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{"Install"})) }) ItInstallsJob(act) }) }) Describe("Apply", func() { act := func() error { return applier.Apply(job) } It("return an error if getting file bundle fails", func() { jobsBc.GetErr = errors.New("fake-get-bundle-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-bundle-error")) }) It("returns an error if checking for installed path fails", func() { bundle.IsInstalledErr = errors.New("fake-is-installed-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-is-installed-error")) }) Context("when job is already installed", func() { BeforeEach(func() { bundle.Installed = true }) It("does not install but only enables job", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{"Enable"})) // no Install }) It("returns error when job enable fails", func() { bundle.EnableError = errors.New("fake-enable-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-enable-error")) }) It("does not download the job template", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs).To(BeNil()) }) ItUpdatesPackages(act) }) Context("when job is not installed", func() { BeforeEach(func() { bundle.Installed = false }) It("installs and enables job", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{"Install", "Enable"})) }) It("returns error when job enable fails", func() { bundle.EnableError = errors.New("fake-enable-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-enable-error")) }) ItInstallsJob(act) ItUpdatesPackages(act) }) }) }) Describe("Configure", func() { It("adds job to the job supervisor", func() { job, bundle := buildJob(jobsBc) fs := fakesys.NewFakeFileSystem() fs.WriteFileString("/path/to/job/monit", "some conf") fs.SetGlob("/path/to/job/*.monit", []string{"/path/to/job/subjob.monit"}) bundle.GetDirPath = "/path/to/job" bundle.GetDirFs = fs err := applier.Configure(job, 0) Expect(err).ToNot(HaveOccurred()) Expect(len(jobSupervisor.AddJobArgs)).To(Equal(2)) Expect(jobSupervisor.AddJobArgs[0]).To(Equal(fakejobsuper.AddJobArgs{ Name: job.Name, Index: 0, ConfigPath: "/path/to/job/monit", })) Expect(jobSupervisor.AddJobArgs[1]).To(Equal(fakejobsuper.AddJobArgs{ Name: job.Name + "_subjob", Index: 0, ConfigPath: "/path/to/job/subjob.monit", })) }) It("does not require monit script", func() { job, bundle := buildJob(jobsBc) fs := fakesys.NewFakeFileSystem() bundle.GetDirFs = fs err := applier.Configure(job, 0) Expect(err).ToNot(HaveOccurred()) Expect(len(jobSupervisor.AddJobArgs)).To(Equal(0)) }) }) Describe("KeepOnly", func() { It("first disables and then uninstalls jobs that are not in keeponly list", func() { _, bundle1 := buildJob(jobsBc) job2, bundle2 := buildJob(jobsBc) _, bundle3 := buildJob(jobsBc) job4, bundle4 := buildJob(jobsBc) jobsBc.ListBundles = []boshbc.Bundle{bundle1, bundle2, bundle3, bundle4} err := applier.KeepOnly([]models.Job{job4, job2}) Expect(err).ToNot(HaveOccurred()) Expect(bundle1.ActionsCalled).To(Equal([]string{"Disable", "Uninstall"})) Expect(bundle2.ActionsCalled).To(Equal([]string{})) Expect(bundle3.ActionsCalled).To(Equal([]string{"Disable", "Uninstall"})) Expect(bundle4.ActionsCalled).To(Equal([]string{})) }) It("returns error when bundle collection fails to return list of installed bundles", func() { jobsBc.ListErr = errors.New("fake-bc-list-error") err := applier.KeepOnly([]models.Job{}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-list-error")) }) It("returns error when bundle collection cannot retrieve bundle for keep-only job", func() { job1, bundle1 := buildJob(jobsBc) jobsBc.ListBundles = []boshbc.Bundle{bundle1} jobsBc.GetErr = errors.New("fake-bc-get-error") err := applier.KeepOnly([]models.Job{job1}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-get-error")) }) It("returns error when at least one bundle cannot be disabled", func() { _, bundle1 := buildJob(jobsBc) jobsBc.ListBundles = []boshbc.Bundle{bundle1} bundle1.DisableErr = errors.New("fake-bc-disable-error") err := applier.KeepOnly([]models.Job{}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-disable-error")) }) It("returns error when at least one bundle cannot be uninstalled", func() { _, bundle1 := buildJob(jobsBc) jobsBc.ListBundles = []boshbc.Bundle{bundle1} bundle1.UninstallErr = errors.New("fake-bc-uninstall-error") err := applier.KeepOnly([]models.Job{}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-uninstall-error")) }) }) }) }
Expect(string(contents[0])).To(Equal("fake-contents-1")) Expect(string(contents[1])).To(Equal("fake-contents-2")) }) It("unmount disk path", func() { _, err := diskUtil.GetFilesContents([]string{"fake-file-path-1"}) Expect(err).ToNot(HaveOccurred()) Expect(mounter.UnmountPartitionPathOrMountPoint).To(Equal("fake-tempdir")) }) It("cleans up temporary directory after reading settings", func() { _, err := diskUtil.GetFilesContents([]string{"fake-file-path-1"}) Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists("fake-tempdir")).To(BeFalse()) }) It("returns error if it fails to create temporary mount directory", func() { fs.TempDirError = errors.New("fake-tempdir-error") _, err := diskUtil.GetFilesContents([]string{"fake-file-path-1"}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-tempdir-error")) }) It("returns error if it fails to mount disk path", func() { mounter.MountErr = errors.New("fake-mount-error") _, err := diskUtil.GetFilesContents([]string{"fake-file-path-1"}) Expect(err).To(HaveOccurred())
}) Describe("Path", func() { It("returns the local blob path", func() { Expect(localBlob.Path()).To(Equal(localBlobPath)) }) }) Describe("Delete", func() { It("deletes the local blob from the file system", func() { err := fs.WriteFileString(localBlobPath, "fake-local-blob-content") Expect(err).ToNot(HaveOccurred()) err = localBlob.Delete() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(localBlobPath)).To(BeFalse()) }) Context("when deleting from the file system fails", func() { JustBeforeEach(func() { fs.RemoveAllStub = func(_ string) error { return bosherr.Error("fake-delete-error") } }) It("returns an error", func() { err := localBlob.Delete() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-delete-error")) }) })
func init() { Describe("compiledPackageApplier", func() { var ( packagesBc *fakebc.FakeBundleCollection blobstore *fakeblob.FakeBlobstore compressor *fakecmd.FakeCompressor fs *fakesys.FakeFileSystem logger boshlog.Logger applier Applier ) BeforeEach(func() { packagesBc = fakebc.NewFakeBundleCollection() blobstore = fakeblob.NewFakeBlobstore() compressor = fakecmd.NewFakeCompressor() fs = fakesys.NewFakeFileSystem() logger = boshlog.NewLogger(boshlog.LevelNone) applier = NewCompiledPackageApplier(packagesBc, true, blobstore, compressor, fs, logger) }) Describe("Prepare & Apply", func() { var ( pkg models.Package bundle *fakebc.FakeBundle ) BeforeEach(func() { pkg, bundle = buildPkg(packagesBc) }) ItInstallsPkg := func(act func() error) { It("returns error when installing package fails", func() { bundle.InstallError = errors.New("fake-install-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-install-error")) }) It("downloads and later cleans up downloaded package blob", func() { blobstore.GetFileName = "/fake-blobstore-file-name" err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs[0]).To(Equal("fake-blobstore-id")) Expect(blobstore.GetFingerprints[0]).To(Equal("fake-blob-sha1")) // downloaded file is cleaned up Expect(blobstore.CleanUpFileName).To(Equal("/fake-blobstore-file-name")) }) It("returns error when downloading package blob fails", func() { blobstore.GetError = errors.New("fake-get-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-error")) }) It("decompresses package blob to tmp path and later cleans it up", func() { fs.TempDirDir = "/fake-tmp-dir" blobstore.GetFileName = "/fake-blobstore-file-name" var tmpDirExistsBeforeInstall bool bundle.InstallCallBack = func() { tmpDirExistsBeforeInstall = true } err := act() Expect(err).ToNot(HaveOccurred()) Expect(compressor.DecompressFileToDirTarballPaths[0]).To(Equal("/fake-blobstore-file-name")) Expect(compressor.DecompressFileToDirDirs[0]).To(Equal("/fake-tmp-dir")) // tmp dir exists before bundle install Expect(tmpDirExistsBeforeInstall).To(BeTrue()) // tmp dir is cleaned up after install Expect(fs.FileExists(fs.TempDirDir)).To(BeFalse()) }) It("returns error when temporary directory creation fails", func() { fs.TempDirError = errors.New("fake-filesystem-tempdir-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-filesystem-tempdir-error")) }) It("returns error when decompressing package blob fails", func() { compressor.DecompressFileToDirErr = errors.New("fake-decompress-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-decompress-error")) }) It("installs bundle from decompressed tmp path of a package blob", func() { fs.TempDirDir = "/fake-tmp-dir" var installedBeforeDecompression bool compressor.DecompressFileToDirCallBack = func() { installedBeforeDecompression = bundle.Installed } err := act() Expect(err).ToNot(HaveOccurred()) // bundle installation did not happen before decompression Expect(installedBeforeDecompression).To(BeFalse()) // make sure that bundle install happened after decompression Expect(bundle.InstallSourcePath).To(Equal("/fake-tmp-dir")) }) } Describe("Prepare", func() { act := func() error { return applier.Prepare(pkg) } It("return an error if getting file bundle fails", func() { packagesBc.GetErr = errors.New("fake-get-bundle-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-bundle-error")) }) It("returns an error if checking for package installation fails", func() { bundle.IsInstalledErr = errors.New("fake-is-installed-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-is-installed-error")) }) Context("when package is already installed", func() { BeforeEach(func() { bundle.Installed = true }) It("does not install", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{})) // no Install }) It("does not download the package", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs).To(BeNil()) }) }) Context("when package is not installed", func() { BeforeEach(func() { bundle.Installed = false }) It("installs package (but does not enable it)", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{"Install"})) }) ItInstallsPkg(act) }) }) Describe("Apply", func() { act := func() error { return applier.Apply(pkg) } It("return an error if getting file bundle fails", func() { packagesBc.GetErr = errors.New("fake-get-bundle-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-get-bundle-error")) }) It("returns an error if checking for package installation fails", func() { bundle.IsInstalledErr = errors.New("fake-is-installed-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-is-installed-error")) }) Context("when package is already installed", func() { BeforeEach(func() { bundle.Installed = true }) It("does not install but only enables package", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{"Enable"})) // no Install }) It("returns error when package enable fails", func() { bundle.EnableError = errors.New("fake-enable-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-enable-error")) }) It("does not download the package", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(blobstore.GetBlobIDs).To(BeNil()) }) }) Context("when package is not installed", func() { BeforeEach(func() { bundle.Installed = false }) It("installs and enables package", func() { err := act() Expect(err).ToNot(HaveOccurred()) Expect(bundle.ActionsCalled).To(Equal([]string{"Install", "Enable"})) }) It("returns error when package enable fails", func() { bundle.EnableError = errors.New("fake-enable-error") err := act() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-enable-error")) }) ItInstallsPkg(act) }) }) }) Describe("KeepOnly", func() { ItReturnsErrors := func() { It("returns error when bundle collection fails to return list of installed bundles", func() { packagesBc.ListErr = errors.New("fake-bc-list-error") err := applier.KeepOnly([]models.Package{}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-list-error")) }) It("returns error when bundle collection cannot retrieve bundle for keep-only package", func() { pkg1, bundle1 := buildPkg(packagesBc) packagesBc.ListBundles = []boshbc.Bundle{bundle1} packagesBc.GetErr = errors.New("fake-bc-get-error") err := applier.KeepOnly([]models.Package{pkg1}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-get-error")) }) It("returns error when at least one bundle cannot be disabled", func() { _, bundle1 := buildPkg(packagesBc) packagesBc.ListBundles = []boshbc.Bundle{bundle1} bundle1.DisableErr = errors.New("fake-bc-disable-error") err := applier.KeepOnly([]models.Package{}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-disable-error")) }) } Context("when operating on packages as a package owner", func() { BeforeEach(func() { applier = NewCompiledPackageApplier(packagesBc, true, blobstore, compressor, fs, logger) }) It("first disables and then uninstalls packages that are not in keeponly list", func() { _, bundle1 := buildPkg(packagesBc) pkg2, bundle2 := buildPkg(packagesBc) _, bundle3 := buildPkg(packagesBc) pkg4, bundle4 := buildPkg(packagesBc) packagesBc.ListBundles = []boshbc.Bundle{bundle1, bundle2, bundle3, bundle4} err := applier.KeepOnly([]models.Package{pkg4, pkg2}) Expect(err).ToNot(HaveOccurred()) Expect(bundle1.ActionsCalled).To(Equal([]string{"Disable", "Uninstall"})) Expect(bundle2.ActionsCalled).To(Equal([]string{})) Expect(bundle3.ActionsCalled).To(Equal([]string{"Disable", "Uninstall"})) Expect(bundle4.ActionsCalled).To(Equal([]string{})) }) ItReturnsErrors() It("returns error when at least one bundle cannot be uninstalled", func() { _, bundle1 := buildPkg(packagesBc) packagesBc.ListBundles = []boshbc.Bundle{bundle1} bundle1.UninstallErr = errors.New("fake-bc-uninstall-error") err := applier.KeepOnly([]models.Package{}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-bc-uninstall-error")) }) }) Context("when operating on packages not as a package owner", func() { BeforeEach(func() { applier = NewCompiledPackageApplier(packagesBc, false, blobstore, compressor, fs, logger) }) It("disables and but does not uninstall packages that are not in keeponly list", func() { _, bundle1 := buildPkg(packagesBc) pkg2, bundle2 := buildPkg(packagesBc) _, bundle3 := buildPkg(packagesBc) pkg4, bundle4 := buildPkg(packagesBc) packagesBc.ListBundles = []boshbc.Bundle{bundle1, bundle2, bundle3, bundle4} err := applier.KeepOnly([]models.Package{pkg4, pkg2}) Expect(err).ToNot(HaveOccurred()) Expect(bundle1.ActionsCalled).To(Equal([]string{"Disable"})) // no Uninstall Expect(bundle2.ActionsCalled).To(Equal([]string{})) Expect(bundle3.ActionsCalled).To(Equal([]string{"Disable"})) // no Uninstall Expect(bundle4.ActionsCalled).To(Equal([]string{})) }) ItReturnsErrors() }) }) }) }
Expect(err.Error()).To(ContainSubstring("fake-read-error")) }) }) }) Describe("RemoveAllJobs", func() { Context("when jobs directory removal succeeds", func() { It("does not return error because all jobs are removed from monit", func() { jobsDir := dirProvider.MonitJobsDir() jobBasename := "/0000_router.monitrc" fs.WriteFileString(jobsDir+jobBasename, "fake-added-job") err := monit.RemoveAllJobs() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(jobsDir)).To(BeFalse()) Expect(fs.FileExists(jobsDir + jobBasename)).To(BeFalse()) }) }) Context("when jobs directory removal fails", func() { It("returns error if removing jobs directory fails", func() { fs.RemoveAllError = errors.New("fake-remove-all-error") err := monit.RemoveAllJobs() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-remove-all-error")) }) }) })
}) Describe("SHA1", func() { It("returns the rendered job list archive sha1", func() { Expect(renderedJobListArchive.SHA1()).To(Equal(renderedJobListArchiveSHA1)) }) }) Describe("Delete", func() { It("deletes the rendered job list archive from the file system", func() { err := fs.MkdirAll(renderedJobListArchivePath, os.ModePerm) Expect(err).ToNot(HaveOccurred()) err = renderedJobListArchive.Delete() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(renderedJobListArchivePath)).To(BeFalse()) }) Context("when deleting from the file system fails", func() { JustBeforeEach(func() { fs.RemoveAllStub = func(_ string) error { return bosherr.Error("fake-delete-error") } }) It("returns an error", func() { err := renderedJobListArchive.Delete() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-delete-error")) }) })
decider := &fakebftdecider.FakeDecider{} ipPoolProvider := bftnetwork.NewIpPoolProvider() networkAssigner := bftnetwork.NewAssigner(networks, nameGenerator, ipPoolProvider, decider, logger) parameterProvider := bftparam.NewParameterProvider(parameters, nameGenerator, decider, networkAssigner, logger) inputGenerator := NewInputGenerator(parameters, parameterProvider, 2, nameGenerator, decider, logger) analyzer := bftanalyzer.NewAnalyzer(logger) deployer = NewDeployer(cliRunner, directorInfo, renderer, inputGenerator, analyzer, fs, logger, false) }) It("runs deploys with generated manifests", func() { fs.ReturnTempFile = fakesys.NewFakeFile("manifest-path", fs) err := deployer.RunDeploys() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists("config-path")).To(BeFalse()) Expect(cmdRunner.RunComplexCommands).To(ConsistOf([]boshsys.Command{ { Name: "bosh", Args: []string{"-n", "-c", "cli-config-path", "update", "cloud-config", "manifest-path"}, }, { Name: "bosh", Args: []string{"-n", "-c", "cli-config-path", "deployment", "manifest-path"}, }, { Name: "bosh", Args: []string{"-n", "-c", "cli-config-path", "deploy"}, }, {
func init() { Describe("settingsService", func() { var ( fs *fakesys.FakeFileSystem fakeDefaultNetworkResolver *fakenet.FakeDefaultNetworkResolver fakeSettingsSource *fakes.FakeSettingsSource ) BeforeEach(func() { fs = fakesys.NewFakeFileSystem() fakeDefaultNetworkResolver = &fakenet.FakeDefaultNetworkResolver{} fakeSettingsSource = &fakes.FakeSettingsSource{} }) buildService := func() (Service, *fakesys.FakeFileSystem) { logger := boshlog.NewLogger(boshlog.LevelNone) service := NewService(fs, "/setting/path.json", fakeSettingsSource, fakeDefaultNetworkResolver, logger) return service, fs } Describe("LoadSettings", func() { var ( fetchedSettings Settings fetcherFuncErr error service Service ) BeforeEach(func() { fetchedSettings = Settings{} fetcherFuncErr = nil }) JustBeforeEach(func() { fakeSettingsSource.SettingsValue = fetchedSettings fakeSettingsSource.SettingsErr = fetcherFuncErr service, fs = buildService() }) Context("when settings fetcher succeeds fetching settings", func() { BeforeEach(func() { fetchedSettings = Settings{AgentID: "some-new-agent-id"} }) Context("when settings contain at most one dynamic network", func() { BeforeEach(func() { fetchedSettings.Networks = Networks{ "fake-net-1": Network{Type: NetworkTypeDynamic}, } }) It("updates the service with settings from the fetcher", func() { err := service.LoadSettings() Expect(err).NotTo(HaveOccurred()) Expect(service.GetSettings().AgentID).To(Equal("some-new-agent-id")) }) It("persists settings to the settings file", func() { err := service.LoadSettings() Expect(err).NotTo(HaveOccurred()) json, err := json.Marshal(fetchedSettings) Expect(err).NotTo(HaveOccurred()) fileContent, err := fs.ReadFile("/setting/path.json") Expect(err).NotTo(HaveOccurred()) Expect(fileContent).To(Equal(json)) }) It("returns any error from writing to the setting file", func() { fs.WriteFileError = errors.New("fs-write-file-error") err := service.LoadSettings() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fs-write-file-error")) }) }) }) Context("when settings fetcher fails fetching settings", func() { BeforeEach(func() { fetcherFuncErr = errors.New("fake-fetch-error") }) Context("when a settings file exists", func() { Context("when settings contain at most one dynamic network", func() { BeforeEach(func() { fs.WriteFile("/setting/path.json", []byte(`{ "agent_id":"some-agent-id", "networks": {"fake-net-1": {"type": "dynamic"}} }`)) fakeDefaultNetworkResolver.GetDefaultNetworkNetwork = Network{ IP: "fake-resolved-ip", Netmask: "fake-resolved-netmask", Gateway: "fake-resolved-gateway", } }) It("returns settings from the settings file with resolved network", func() { err := service.LoadSettings() Expect(err).ToNot(HaveOccurred()) Expect(service.GetSettings()).To(Equal(Settings{ AgentID: "some-agent-id", Networks: Networks{ "fake-net-1": Network{ Type: NetworkTypeDynamic, IP: "fake-resolved-ip", Netmask: "fake-resolved-netmask", Gateway: "fake-resolved-gateway", Resolved: true, }, }, })) }) }) }) Context("when non-unmarshallable settings file exists", func() { It("returns any error from the fetcher", func() { fs.WriteFile("/setting/path.json", []byte(`$%^&*(`)) err := service.LoadSettings() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-fetch-error")) Expect(service.GetSettings()).To(Equal(Settings{})) }) }) Context("when no settings file exists", func() { It("returns any error from the fetcher", func() { err := service.LoadSettings() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-fetch-error")) Expect(service.GetSettings()).To(Equal(Settings{})) }) }) }) }) Describe("InvalidateSettings", func() { It("removes the settings file", func() { fakeSettingsSource.SettingsValue = Settings{} fakeSettingsSource.SettingsErr = nil service, fs := buildService() fs.WriteFile("/setting/path.json", []byte(`{}`)) err := service.InvalidateSettings() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists("/setting/path.json")).To(BeFalse()) }) It("returns err if removing settings file errored", func() { fakeSettingsSource.SettingsValue = Settings{} fakeSettingsSource.SettingsErr = nil service, fs := buildService() fs.RemoveAllError = errors.New("fs-remove-all-error") err := service.InvalidateSettings() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fs-remove-all-error")) }) }) Describe("GetSettings", func() { var ( loadedSettings Settings service Service ) BeforeEach(func() { loadedSettings = Settings{AgentID: "some-agent-id"} }) JustBeforeEach(func() { fakeSettingsSource.SettingsValue = loadedSettings fakeSettingsSource.SettingsErr = nil service, _ = buildService() err := service.LoadSettings() Expect(err).NotTo(HaveOccurred()) }) Context("when there is are no dynamic networks", func() { It("returns settings without modifying any networks", func() { Expect(service.GetSettings()).To(Equal(loadedSettings)) }) It("does not try to determine default network", func() { _ = service.GetSettings() Expect(fakeDefaultNetworkResolver.GetDefaultNetworkCalled).To(BeFalse()) }) }) Context("when there is network that needs to be resolved (ip, netmask, or mac are not set)", func() { BeforeEach(func() { loadedSettings = Settings{ Networks: map[string]Network{ "fake-net1": Network{ IP: "fake-net1-ip", Netmask: "fake-net1-netmask", Mac: "fake-net1-mac", Gateway: "fake-net1-gateway", }, "fake-net2": Network{ Gateway: "fake-net2-gateway", DNS: []string{"fake-net2-dns"}, }, }, } }) Context("when default network can be retrieved", func() { BeforeEach(func() { fakeDefaultNetworkResolver.GetDefaultNetworkNetwork = Network{ IP: "fake-resolved-ip", Netmask: "fake-resolved-netmask", Gateway: "fake-resolved-gateway", } }) It("returns settings with resolved dynamic network ip, netmask, gateway and keeping everything else the same", func() { settings := service.GetSettings() Expect(settings).To(Equal(Settings{ Networks: map[string]Network{ "fake-net1": Network{ IP: "fake-net1-ip", Netmask: "fake-net1-netmask", Mac: "fake-net1-mac", Gateway: "fake-net1-gateway", }, "fake-net2": Network{ IP: "fake-resolved-ip", Netmask: "fake-resolved-netmask", Gateway: "fake-resolved-gateway", DNS: []string{"fake-net2-dns"}, Resolved: true, }, }, })) }) }) Context("when default network fails to be retrieved", func() { BeforeEach(func() { fakeDefaultNetworkResolver.GetDefaultNetworkErr = errors.New("fake-get-default-network-err") }) It("returns error", func() { settings := service.GetSettings() Expect(settings).To(Equal(loadedSettings)) }) }) }) }) }) }
It("runs a failing Powershell command and returns error", func() { cmdRunner.AddCmdResult("/fake-temp-file.fake-ext", fakesys.FakeCmdResult{ Error: errors.New("failed"), }) _, _, err := scriptRunner.Run("") Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("failed")) }) It("cleans temporary files", func() { _, _, err := scriptRunner.Run("") Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists("/fake-temp-file")).To(BeFalse()) Expect(fs.FileExists("/fake-temp-file.fake-ext")).To(BeFalse()) }) Context("filesystem errors", func() { Context("when creating Tempfile fails", func() { It("errors out", func() { fs.TempFileError = errors.New("boo") _, _, err := scriptRunner.Run("") Expect(err.Error()).To(Equal("Creating tempfile: boo")) }) }) Context("when writing to the Tempfile fails", func() { It("errors out", func() {
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()) _, err = renderedJobListCompressor.Compress(renderedJobList) Expect(err).ToNot(HaveOccurred()) Expect(fakeFS.FileExists("fake-rendered-job-list-path")).To(BeFalse()) }) }) }) })
Context("when command succeeds", func() { BeforeEach(func() { cmdRunner.AddCmdResult("/path-to-script", fakesys.FakeCmdResult{ Stdout: "fake-stdout", Stderr: "fake-stderr", ExitStatus: 0, Error: nil, }) }) It("saves stdout/stderr to log file", func() { err := genericScript.Run() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(stdoutLogPath)).To(BeTrue()) Expect(fs.FileExists(stderrLogPath)).To(BeTrue()) stdout, err := fs.ReadFileString(stdoutLogPath) Expect(err).ToNot(HaveOccurred()) Expect(stdout).To(Equal("fake-stdout")) stderr, err := fs.ReadFileString(stderrLogPath) Expect(err).ToNot(HaveOccurred()) Expect(stderr).To(Equal("fake-stderr")) }) }) Context("when command fails", func() { BeforeEach(func() { cmdRunner.AddCmdResult("/path-to-script", fakesys.FakeCmdResult{
blobSHA1 = "fake-sha1" fileName = "tarball.tgz" blobstore.GetFileName = fileName fakeError = errors.New("Initial error") extractor = NewExtractor(fs, compressor, blobstore, logger) }) Describe("Cleanup", func() { BeforeEach(func() { err := extractor.Extract(blobID, blobSHA1, targetDir) Expect(err).ToNot(HaveOccurred()) }) It("deletes the extracted temp file", func() { Expect(fs.FileExists(targetDir)).To(BeTrue()) err := extractor.Cleanup(blobID, targetDir) Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(targetDir)).To(BeFalse()) }) It("deletes the stored blob", func() { err := extractor.Cleanup(blobID, targetDir) Expect(err).ToNot(HaveOccurred()) Expect(blobstore.DeleteBlobID).To(Equal(blobID)) }) }) Describe("Extract", func() { Context("when the specified blobID exists in the blobstore", func() { It("creates the installed package dir if it does not exist", func() {
}) It("fails reading the DNS records from the blobstore file", func() { fakeFileSystem.RegisterReadFileError("fake-blobstore-file-path", errors.New("fake-error")) response, err := syncDNS.Run("fake-blobstore-id", "fake-fingerprint") Expect(err).To(HaveOccurred()) Expect(response).To(Equal("")) Expect(err.Error()).To(ContainSubstring("Reading fileName")) }) It("deletes the file once read", func() { _, err := syncDNS.Run("fake-blobstore-id", "fake-fingerprint") Expect(err).ToNot(HaveOccurred()) Expect(fakeFileSystem.FileExists("fake-blobstore-file-path")).To(BeFalse()) }) It("logs when the dns blob file can't be deleted", func() { fakeFileSystem.RegisterRemoveAllError("fake-blobstore-file-path", errors.New("fake-file-path-error")) _, err := syncDNS.Run("fake-blobstore-id", "fake-fingerprint") Expect(err).ToNot(HaveOccurred()) tag, message, _ := logger.InfoArgsForCall(0) Expect(tag).To(Equal("Sync DNS action")) Expect(message).To(Equal("Failed to remove dns blob file at path 'fake-blobstore-file-path'")) }) It("saves DNS records to the platform", func() { response, err := syncDNS.Run("fake-blobstore-id", "fake-fingerprint") Expect(err).ToNot(HaveOccurred())
fs.ReturnTempFile = tempFile defer fs.RemoveAll(tempFile.Name()) fileName, err := blobstore.Get("fake-blob-id", "") Expect(err).ToNot(HaveOccurred()) Expect(len(runner.RunCommands)).To(Equal(1)) Expect(runner.RunCommands[0]).To(Equal([]string{ "bosh-blobstore-fake-provider", "-c", configPath, "get", "fake-blob-id", tempFile.Name(), })) Expect(fileName).To(Equal(tempFile.Name())) Expect(fs.FileExists(tempFile.Name())).To(BeTrue()) }) It("external get errs when temp file create errs", func() { fs.TempFileError = errors.New("fake-error") fileName, err := blobstore.Get("fake-blob-id", "") Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-error")) Expect(fileName).To(BeEmpty()) }) It("external get errs when external cli errs", func() { tempFile, err := fs.TempFile("bosh-blobstore-external-TestGetErrsWhenExternalCliErrs") Expect(err).ToNot(HaveOccurred())
WorkingDir: "/fake-working-dir", } }) Describe("RunCommand", func() { It("cleans logs directory", func() { err := fs.MkdirAll("/fake-base-dir/fake-log-dir-name/", os.FileMode(0750)) Expect(err).ToNot(HaveOccurred()) err = fs.WriteFile("/fake-base-dir/fake-log-dir-name/old-file", []byte("test-data")) Expect(err).ToNot(HaveOccurred()) _, err = runner.RunCommand("fake-log-dir-name", "fake-log-file-name", cmd) Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists("/fake-base-dir/fake-log-dir-name/old-file")).To(BeFalse()) }) It("returns an error if it fails to remove previous logs directory", func() { fs.RemoveAllError = errors.New("fake-remove-all-error") _, err := runner.RunCommand("fake-log-dir-name", "fake-log-file-name", cmd) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-remove-all-error")) }) It("returns an error if it fails to create logs directory", func() { fs.MkdirAllError = errors.New("fake-mkdir-all-error") _, err := runner.RunCommand("fake-log-dir-name", "fake-log-file-name", cmd) Expect(err).To(HaveOccurred())
Expect(count).To(Equal(0)) }) }) Describe("cert.Manager implementations", func() { var ( fakeFs *fakesys.FakeFileSystem fakeCmd *fakesys.FakeCmdRunner certManager cert.Manager ) SharedLinuxCertManagerExamples := func(certBasePath, certUpdateProgram string) { It("writes 1 cert to a file", func() { err := certManager.UpdateCertificates(cert1) Expect(err).NotTo(HaveOccurred()) Expect(fakeFs.FileExists(fmt.Sprintf("%s/bosh-trusted-cert-1.crt", certBasePath))).To(BeTrue()) }) It("writes each cert to its own file", func() { certs := fmt.Sprintf("%s\n%s\n", cert1, cert1) err := certManager.UpdateCertificates(certs) Expect(err).NotTo(HaveOccurred()) Expect(fakeFs.FileExists(fmt.Sprintf("%s/bosh-trusted-cert-1.crt", certBasePath))).To(BeTrue()) Expect(fakeFs.FileExists(fmt.Sprintf("%s/bosh-trusted-cert-2.crt", certBasePath))).To(BeTrue()) Expect(countFiles(fakeFs, certBasePath)).To(Equal(2)) }) It("deletes all certs when passed an empty string", func() { fakeFs.WriteFileString(fmt.Sprintf("%s/bosh-trusted-cert-1.crt", certBasePath), "goodbye") fakeFs.SetGlob(fmt.Sprintf("%s/bosh-trusted-cert-*", certBasePath), []string{
fs.WriteFileString("source-path", "") err := cache.Save("source-path", &fakeSource{ sha1: "fake-sha1", url: "http://foo.bar.com", description: "some tarball", }) Expect(err).ToNot(HaveOccurred()) path, found := cache.Get(&fakeSource{ sha1: "fake-sha1", url: "http://foo.bar.com", description: "some tarball", }) Expect(found).To(BeTrue()) Expect(fs.FileExists(path)).To(BeTrue()) }) It("is a cache miss when a tarball from a different url has been downloaded, even if SHA1 matches", func() { fs.WriteFileString("source-path", "") err := cache.Save("source-path", &fakeSource{ sha1: "fake-sha1", url: "http://foo.bar.com", description: "some tarball", }) Expect(err).ToNot(HaveOccurred()) _, found := cache.Get(&fakeSource{ sha1: "fake-sha1", url: "http://baz.bar.com",
fs *fakesys.FakeFileSystem cdrom *fakecdrom.FakeCdrom cdutil boshdevutil.DeviceUtil logger boshlog.Logger ) BeforeEach(func() { fs = fakesys.NewFakeFileSystem() cdrom = fakecdrom.NewFakeCdrom(fs, "env", "fake env contents") logger = boshlog.NewLogger(boshlog.LevelNone) }) JustBeforeEach(func() { cdutil = boshcdrom.NewCdUtil("/fake/settings/dir", fs, cdrom, logger) }) It("gets file contents from CDROM", func() { contents, err := cdutil.GetFilesContents([]string{"env"}) Expect(err).NotTo(HaveOccurred()) Expect(cdrom.Mounted).To(Equal(false)) Expect(cdrom.MediaAvailable).To(Equal(false)) Expect(fs.FileExists("/fake/settings/dir")).To(Equal(true)) Expect(cdrom.MountMountPath).To(Equal("/fake/settings/dir")) Expect(len(contents)).To(Equal(1)) Expect(contents[0]).To(Equal([]byte("fake env contents"))) }) })
}) Describe("Path", func() { It("returns the rendered job path", func() { Expect(renderedJob.Path()).To(Equal(renderedJobPath)) }) }) Describe("Delete", func() { It("deletes the rendered job path from the file system", func() { err := fs.MkdirAll(renderedJobPath, os.ModePerm) Expect(err).ToNot(HaveOccurred()) err = renderedJob.Delete() Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(renderedJobPath)).To(BeFalse()) }) Context("when deleting from the file system fails", func() { JustBeforeEach(func() { fs.RemoveAllStub = func(_ string) error { return bosherr.Error("fake-delete-error") } }) It("returns an error", func() { err := renderedJob.Delete() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-delete-error")) }) })