1package cmd_test 2 3import ( 4 . "github.com/cloudfoundry/bosh-cli/cmd" 5 6 . "github.com/cloudfoundry/bosh-cli/release/resource" 7 8 . "github.com/onsi/ginkgo" 9 . "github.com/onsi/gomega" 10 11 boshrel "github.com/cloudfoundry/bosh-cli/release" 12 boshjob "github.com/cloudfoundry/bosh-cli/release/job" 13 boshpkg "github.com/cloudfoundry/bosh-cli/release/pkg" 14 boshtbl "github.com/cloudfoundry/bosh-cli/ui/table" 15 16 fakecrypto "github.com/cloudfoundry/bosh-cli/crypto/fakes" 17 fakerel "github.com/cloudfoundry/bosh-cli/release/releasefakes" 18 fakeui "github.com/cloudfoundry/bosh-cli/ui/fakes" 19 fakefu "github.com/cloudfoundry/bosh-utils/fileutil/fakes" 20 fakes2 "github.com/cloudfoundry/bosh-utils/system/fakes" 21 22 "github.com/cloudfoundry/bosh-cli/crypto/fakes" 23 "github.com/cloudfoundry/bosh-cli/release/license" 24 "github.com/cloudfoundry/bosh-utils/errors" 25) 26 27var _ = Describe("RedigestRelease", func() { 28 29 var ( 30 releaseReader *fakerel.FakeReader 31 ui *fakeui.FakeUI 32 fmv *fakefu.FakeMover 33 releaseWriter *fakerel.FakeWriter 34 command RedigestReleaseCmd 35 args RedigestReleaseArgs 36 fakeDigestCalculator *fakes.FakeDigestCalculator 37 releaseWriterTempDestination string 38 fs *fakes2.FakeFileSystem 39 ) 40 41 BeforeEach(func() { 42 releaseReader = &fakerel.FakeReader{} 43 releaseWriter = &fakerel.FakeWriter{} 44 ui = &fakeui.FakeUI{} 45 fmv = &fakefu.FakeMover{} 46 fs = fakes2.NewFakeFileSystem() 47 48 fakeDigestCalculator = fakes.NewFakeDigestCalculator() 49 command = NewRedigestReleaseCmd(releaseReader, releaseWriter, fakeDigestCalculator, fmv, fs, ui) 50 }) 51 var fakeSha128Release *fakerel.FakeRelease 52 53 job1ResourcePath := "/job-resource-1-path" 54 pkg1ResourcePath := "/pkg-resource-1-path" 55 compiledPackage1ResourcePath := "/compiled-pkg-resource-path" 56 licenseResourcePath := "/license-resource-path" 57 fileContentSha1 := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed" 58 59 createFakeFileWithKnownSha1 := func() *fakes2.FakeFile { 60 return &fakes2.FakeFile{ 61 Contents: []byte("hello world"), 62 } 63 } 64 65 BeforeEach(func() { 66 args = RedigestReleaseArgs{ 67 Path: "/some/release_128.tgz", 68 Destination: FileArg{ExpandedPath: "/some/release_256.tgz"}, 69 } 70 71 fs.RegisterOpenFile(job1ResourcePath, createFakeFileWithKnownSha1()) 72 fs.RegisterOpenFile(pkg1ResourcePath, createFakeFileWithKnownSha1()) 73 fs.RegisterOpenFile(compiledPackage1ResourcePath, createFakeFileWithKnownSha1()) 74 fs.RegisterOpenFile(licenseResourcePath, createFakeFileWithKnownSha1()) 75 76 fakeSha128Release = &fakerel.FakeRelease{} 77 jobSha128 := boshjob.NewJob(NewResourceWithBuiltArchive("job-resource-1", "job-sha128-fp", job1ResourcePath, fileContentSha1)) 78 packageSha128 := boshpkg.NewPackage(NewResourceWithBuiltArchive("pkg-resource-1", "pkg-sha128-fp", pkg1ResourcePath, fileContentSha1), nil) 79 compiledPackageSha128 := boshpkg.NewCompiledPackageWithArchive("compiledpkg-resource-1", "compiledpkg-sha128-fp", "1", compiledPackage1ResourcePath, fileContentSha1, nil) 80 81 fakeSha128Release.JobsReturns([]*boshjob.Job{jobSha128}) 82 fakeSha128Release.PackagesReturns([]*boshpkg.Package{packageSha128}) 83 fakeSha128Release.LicenseReturns(license.NewLicense(NewResourceWithBuiltArchive("license-resource-path", "lic-sha128-fp", licenseResourcePath, fileContentSha1))) 84 fakeSha128Release.CompiledPackagesReturns([]*boshpkg.CompiledPackage{compiledPackageSha128}) 85 86 fakeSha128Release.CopyWithStub = func(jobs []*boshjob.Job, pkgs []*boshpkg.Package, lic *license.License, compiledPackages []*boshpkg.CompiledPackage) boshrel.Release { 87 fakeSha256Release := &fakerel.FakeRelease{} 88 fakeSha256Release.NameReturns("custom-name") 89 fakeSha256Release.VersionReturns("custom-ver") 90 fakeSha256Release.CommitHashWithMarkReturns("commit") 91 fakeSha256Release.JobsReturns(jobs) 92 fakeSha256Release.PackagesReturns(pkgs) 93 fakeSha256Release.LicenseReturns(lic) 94 fakeSha256Release.CompiledPackagesReturns(compiledPackages) 95 return fakeSha256Release 96 } 97 98 fakeDigestCalculator.SetCalculateBehavior(map[string]fakecrypto.CalculateInput{ 99 job1ResourcePath: {DigestStr: "sha256:jobsha256"}, 100 pkg1ResourcePath: {DigestStr: "sha256:pkgsha256"}, 101 licenseResourcePath: {DigestStr: "sha256:licsha256"}, 102 compiledPackage1ResourcePath: {DigestStr: "sha256:compiledpkgsha256"}, 103 }) 104 105 releaseReader.ReadReturns(fakeSha128Release, nil) 106 releaseWriterTempDestination = "/some/temp/release_256.tgz" 107 releaseWriter.WriteReturns(releaseWriterTempDestination, nil) 108 }) 109 110 Context("Given a valid sha128 release tar", func() { 111 It("Should convert it to a sha256 release tar", func() { 112 err := command.Run(args) 113 Expect(err).ToNot(HaveOccurred()) 114 115 Expect(releaseReader.ReadCallCount()).ToNot(Equal(0)) 116 117 readPathArg := releaseReader.ReadArgsForCall(0) 118 Expect(readPathArg).To(Equal("/some/release_128.tgz")) 119 120 Expect(releaseWriter.WriteCallCount()).To(Equal(1)) 121 sha2ifyRelease, _ := releaseWriter.WriteArgsForCall(0) 122 123 Expect(sha2ifyRelease).NotTo(BeNil()) 124 125 Expect(sha2ifyRelease.License()).ToNot(BeNil()) 126 Expect(sha2ifyRelease.License().ArchiveDigest()).To(Equal("sha256:licsha256")) 127 128 Expect(sha2ifyRelease.Jobs()).To(HaveLen(1)) 129 Expect(sha2ifyRelease.Jobs()[0].ArchiveDigest()).To(Equal("sha256:jobsha256")) 130 131 Expect(sha2ifyRelease.Packages()).To(HaveLen(1)) 132 Expect(sha2ifyRelease.Packages()[0].ArchiveDigest()).To(Equal("sha256:pkgsha256")) 133 134 Expect(sha2ifyRelease.CompiledPackages()).To(HaveLen(1)) 135 Expect(sha2ifyRelease.CompiledPackages()[0].ArchiveDigest()).To(Equal("sha256:compiledpkgsha256")) 136 137 Expect(fmv.MoveCallCount()).To(Equal(1)) 138 139 src, dst := fmv.MoveArgsForCall(0) 140 Expect(src).To(Equal(releaseWriterTempDestination)) 141 Expect(dst).To(Equal(args.Destination.ExpandedPath)) 142 143 Expect(ui.Tables[0]).To(Equal(boshtbl.Table{ 144 Header: []boshtbl.Header{ 145 boshtbl.NewHeader("Name"), 146 boshtbl.NewHeader("Version"), 147 boshtbl.NewHeader("Commit Hash"), 148 boshtbl.NewHeader("Archive"), 149 }, 150 Rows: [][]boshtbl.Value{ 151 { 152 boshtbl.NewValueString("custom-name"), 153 boshtbl.NewValueString("custom-ver"), 154 boshtbl.NewValueString("commit"), 155 boshtbl.NewValueString("/some/release_256.tgz"), 156 }, 157 }, 158 Transpose: true, 159 })) 160 }) 161 162 Context("when unable to write the sha256 tarball", func() { 163 BeforeEach(func() { 164 releaseWriter.WriteReturns("", errors.Error("disaster")) 165 }) 166 167 It("should return an error", func() { 168 err := command.Run(args) 169 Expect(err).To(HaveOccurred()) 170 Expect(err.Error()).To(ContainSubstring("disaster")) 171 }) 172 }) 173 174 Context("when rehashing a licence fails", func() { 175 BeforeEach(func() { 176 fakeDigestCalculator.SetCalculateBehavior(map[string]fakecrypto.CalculateInput{ 177 job1ResourcePath: {DigestStr: "sha256:jobsha256"}, 178 pkg1ResourcePath: {DigestStr: "sha256:pkgsha256"}, 179 compiledPackage1ResourcePath: {DigestStr: "sha256:compiledpkgsha256"}, 180 licenseResourcePath: {Err: errors.Error("Unknown algorithm")}, 181 }) 182 }) 183 184 It("should return an error", func() { 185 err := command.Run(args) 186 Expect(err).To(HaveOccurred()) 187 Expect(err.Error()).To(ContainSubstring("Unknown algorithm")) 188 }) 189 }) 190 191 Context("when rehashing compiled packages fails", func() { 192 BeforeEach(func() { 193 fakeDigestCalculator.SetCalculateBehavior(map[string]fakecrypto.CalculateInput{ 194 job1ResourcePath: {DigestStr: "sha256:jobsha256"}, 195 pkg1ResourcePath: {DigestStr: "sha256:pkgsha256"}, 196 compiledPackage1ResourcePath: {Err: errors.Error("Unknown algorithm")}, 197 licenseResourcePath: {DigestStr: "sha256:licsha256"}, 198 }) 199 }) 200 201 It("should return an error", func() { 202 err := command.Run(args) 203 Expect(err).To(HaveOccurred()) 204 Expect(err.Error()).To(ContainSubstring("Unknown algorithm")) 205 }) 206 }) 207 208 Context("when rehashing packages fails", func() { 209 BeforeEach(func() { 210 fakeDigestCalculator.SetCalculateBehavior(map[string]fakecrypto.CalculateInput{ 211 job1ResourcePath: {DigestStr: "sha256:jobsha256"}, 212 pkg1ResourcePath: {Err: errors.Error("Unknown algorithm")}, 213 compiledPackage1ResourcePath: {DigestStr: "sha256:compiledpkgsha256"}, 214 licenseResourcePath: {DigestStr: "sha256:licsha256"}, 215 }) 216 }) 217 218 It("should return an error", func() { 219 err := command.Run(args) 220 Expect(err).To(HaveOccurred()) 221 Expect(err.Error()).To(ContainSubstring("Unknown algorithm")) 222 }) 223 }) 224 225 Context("when rehashing jobs fails", func() { 226 BeforeEach(func() { 227 fakeDigestCalculator.SetCalculateBehavior(map[string]fakecrypto.CalculateInput{ 228 job1ResourcePath: {Err: errors.Error("Unknown algorithm")}, 229 pkg1ResourcePath: {DigestStr: "sha256:pkgsha256"}, 230 compiledPackage1ResourcePath: {DigestStr: "sha256:compiledpkgsha256"}, 231 licenseResourcePath: {DigestStr: "sha256:licsha256"}, 232 }) 233 }) 234 235 It("should return an error", func() { 236 err := command.Run(args) 237 Expect(err).To(HaveOccurred()) 238 Expect(err.Error()).To(ContainSubstring("Unknown algorithm")) 239 }) 240 }) 241 242 Context("when no licence is provided", func() { 243 BeforeEach(func() { 244 fakeSha128Release.LicenseReturns(nil) 245 fakeDigestCalculator.SetCalculateBehavior(map[string]fakecrypto.CalculateInput{ 246 job1ResourcePath: {DigestStr: "sha256:jobsha256"}, 247 pkg1ResourcePath: {DigestStr: "sha256:pkgsha256"}, 248 compiledPackage1ResourcePath: {DigestStr: "sha256:compiledpkgsha256"}, 249 }) 250 }) 251 252 It("should not return an error", func() { 253 err := command.Run(args) 254 Expect(err).ToNot(HaveOccurred()) 255 }) 256 }) 257 258 Context("When unable to move sha2fyied release to destination", func() { 259 BeforeEach(func() { 260 fmv.MoveReturns(errors.Error("disaster")) 261 }) 262 263 It("Should return an error", func() { 264 err := command.Run(args) 265 Expect(err).To(HaveOccurred()) 266 Expect(err.Error()).To(ContainSubstring("disaster")) 267 }) 268 }) 269 }) 270 271 Context("Given an invalid sha128 release tar", func() { 272 Context("Given a job that does not verify", func() { 273 BeforeEach(func() { 274 fs.RegisterOpenFile(job1ResourcePath, &fakes2.FakeFile{ 275 Contents: []byte("content that does not match expected sha1"), 276 }) 277 }) 278 279 It("should return an error", func() { 280 err := command.Run(args) 281 Expect(err).To(HaveOccurred()) 282 Expect(err.Error()).To(ContainSubstring("Expected stream to have digest")) 283 284 }) 285 }) 286 287 Context("Given a package that does not verify", func() { 288 BeforeEach(func() { 289 fs.RegisterOpenFile(pkg1ResourcePath, &fakes2.FakeFile{ 290 Contents: []byte("content that does not match expected sha1"), 291 }) 292 }) 293 294 It("should return an error", func() { 295 err := command.Run(args) 296 Expect(err).To(HaveOccurred()) 297 Expect(err.Error()).To(ContainSubstring("Expected stream to have digest")) 298 299 }) 300 }) 301 302 Context("Given a compiled package that does not verify", func() { 303 BeforeEach(func() { 304 fs.RegisterOpenFile(compiledPackage1ResourcePath, &fakes2.FakeFile{ 305 Contents: []byte("content that does not match expected sha1"), 306 }) 307 }) 308 309 It("should return an error", func() { 310 err := command.Run(args) 311 Expect(err).To(HaveOccurred()) 312 Expect(err.Error()).To(ContainSubstring("Expected stream to have digest")) 313 314 }) 315 }) 316 317 Context("Given a license that does not verify", func() { 318 BeforeEach(func() { 319 fs.RegisterOpenFile(licenseResourcePath, &fakes2.FakeFile{ 320 Contents: []byte("content that does not match expected sha1"), 321 }) 322 }) 323 324 It("should return an error", func() { 325 err := command.Run(args) 326 Expect(err).To(HaveOccurred()) 327 Expect(err.Error()).To(ContainSubstring("Expected stream to have digest")) 328 329 }) 330 }) 331 }) 332 333 Context("Given a bad file path", func() { 334 BeforeEach(func() { 335 args = RedigestReleaseArgs{ 336 Path: "/some/release_128.tgz", 337 Destination: FileArg{ExpandedPath: "/some/release_256.tgz"}, 338 } 339 340 releaseReader.ReadReturns(nil, errors.Error("disaster")) 341 }) 342 343 It("Should return an error", func() { 344 err := command.Run(args) 345 Expect(err).To(HaveOccurred()) 346 Expect(err.Error()).To(ContainSubstring("disaster")) 347 }) 348 }) 349}) 350