diff --git a/internal/commands/update_stemcell.go b/internal/commands/update_stemcell.go index b70b68db..88e4505e 100644 --- a/internal/commands/update_stemcell.go +++ b/internal/commands/update_stemcell.go @@ -97,16 +97,19 @@ func (update UpdateStemcell) Execute(args []string) error { update.Logger.Printf("No change for release %q\n", rel.Name) continue } - - local, err := releaseSource.DownloadRelease(update.Options.ReleasesDir, remote) - if err != nil { - return fmt.Errorf("while downloading release %q, encountered error: %w", rel.Name, err) - } - lock := &kilnfileLock.Releases[i] - lock.SHA1 = local.Lock.SHA1 + lock.RemotePath = remote.RemotePath lock.RemoteSource = remote.RemoteSource + lock.SHA1 = remote.SHA1 + if remote.SHA1 == "" || remote.SHA1 == "not-calculated" { + // release source needs to download. + local, err := releaseSource.DownloadRelease(update.Options.ReleasesDir, remote) + if err != nil { + return fmt.Errorf("while downloading release %q, encountered error: %w", rel.Name, err) + } + lock.SHA1 = local.Lock.SHA1 + } } kilnfileLock.Stemcell.Version = trimmedInputVersion diff --git a/internal/commands/update_stemcell_test.go b/internal/commands/update_stemcell_test.go index 477e0e8f..3c4edf6f 100644 --- a/internal/commands/update_stemcell_test.go +++ b/internal/commands/update_stemcell_test.go @@ -34,11 +34,15 @@ var _ = Describe("UpdateStemcell", func() { release1Version = "1" release2Name = "release2" release2Version = "2" + release3Name = "release3" + release3Version = "3" newRelease1SHA = "new-sha1-1" newRelease1RemotePath = "new-remote-path-1" newRelease2SHA = "new-sha1-2" newRelease2RemotePath = "new-remote-path-2" + newRelease3SHA = "new-sha1-3" + newRelease3RemotePath = "new-remote-path-3" publishableReleaseSourceID = "publishable" unpublishableReleaseSourceID = "test-only" @@ -66,8 +70,9 @@ var _ = Describe("UpdateStemcell", func() { Version: "^1", }, Releases: []cargo.BOSHReleaseTarballSpecification{ - {Name: release1Name, GitHubRepository: "https://example.com/lemon", Version: "*"}, + {Name: release1Name, GitHubRepository: "https://example.com/lemon", Version: "*"}, {Name: release2Name, GitHubRepository: "https://example.com/orange", Version: "*"}, + {Name: release3Name, GitHubRepository: "https://example.com/pomelo", Version: "*"}, }, } kilnfileLock = cargo.KilnfileLock{ @@ -86,6 +91,13 @@ var _ = Describe("UpdateStemcell", func() { RemoteSource: "old-remote-source-2", RemotePath: "old-remote-path-2", }, + { + Name: release3Name, + Version: release3Version, + SHA1: "old-sha-3", + RemoteSource: "old-remote-source-3", + RemotePath: "old-remote-path-3", + }, }, Stemcell: cargo.Stemcell{ OS: "old-os", @@ -101,6 +113,7 @@ var _ = Describe("UpdateStemcell", func() { Name: release1Name, Version: release1Version, RemotePath: newRelease1RemotePath, RemoteSource: publishableReleaseSourceID, + SHA1: "", } return remote, nil case release2Name: @@ -108,6 +121,15 @@ var _ = Describe("UpdateStemcell", func() { Name: release2Name, Version: release2Version, RemotePath: newRelease2RemotePath, RemoteSource: unpublishableReleaseSourceID, + SHA1: "not-calculated", + } + return remote, nil + case release3Name: + remote := cargo.BOSHReleaseTarballLock{ + Name: release3Name, Version: release3Version, + RemotePath: newRelease3RemotePath, + RemoteSource: publishableReleaseSourceID, + SHA1: newRelease3SHA, } return remote, nil default: @@ -122,6 +144,7 @@ var _ = Describe("UpdateStemcell", func() { Name: release1Name, Version: release1Version, RemotePath: newRelease1RemotePath, RemoteSource: publishableReleaseSourceID, + SHA1: "", } return remote, nil case release2Name: @@ -129,6 +152,15 @@ var _ = Describe("UpdateStemcell", func() { Name: release2Name, Version: release2Version, RemotePath: newRelease2RemotePath, RemoteSource: unpublishableReleaseSourceID, + SHA1: "not-calculated", + } + return remote, nil + case release3Name: + remote := cargo.BOSHReleaseTarballLock{ + Name: release3Name, Version: release3Version, + RemotePath: newRelease3RemotePath, + RemoteSource: publishableReleaseSourceID, + SHA1: newRelease3SHA, } return remote, nil default: @@ -151,7 +183,7 @@ var _ = Describe("UpdateStemcell", func() { } return local, nil default: - panic("unexpected release name '"+remote.Name +"'") + panic("unexpected release name '" + remote.Name + "'") } }) @@ -192,7 +224,7 @@ var _ = Describe("UpdateStemcell", func() { OS: newStemcellOS, Version: newStemcellVersion, })) - Expect(updatedLockfile.Releases).To(HaveLen(2)) + Expect(updatedLockfile.Releases).To(HaveLen(3)) Expect(updatedLockfile.Releases).To(ContainElement( cargo.BOSHReleaseTarballLock{ Name: release1Name, @@ -211,6 +243,15 @@ var _ = Describe("UpdateStemcell", func() { RemotePath: newRelease2RemotePath, }, )) + Expect(updatedLockfile.Releases).To(ContainElement( + cargo.BOSHReleaseTarballLock{ + Name: release3Name, + Version: release3Version, + SHA1: newRelease3SHA, + RemoteSource: publishableReleaseSourceID, + RemotePath: newRelease3RemotePath, + }, + )) }) It("looks up the correct releases", func() { @@ -219,7 +260,7 @@ var _ = Describe("UpdateStemcell", func() { }) Expect(err).NotTo(HaveOccurred()) - Expect(releaseSource.GetMatchedReleaseCallCount()).To(Equal(2)) + Expect(releaseSource.GetMatchedReleaseCallCount()).To(Equal(3)) req1 := releaseSource.GetMatchedReleaseArgsForCall(0) Expect(req1).To(Equal(cargo.BOSHReleaseTarballSpecification{ @@ -234,6 +275,13 @@ var _ = Describe("UpdateStemcell", func() { StemcellOS: newStemcellOS, StemcellVersion: newStemcellVersion, GitHubRepository: "https://example.com/orange", })) + + req3 := releaseSource.GetMatchedReleaseArgsForCall(2) + Expect(req3).To(Equal(cargo.BOSHReleaseTarballSpecification{ + Name: release3Name, Version: release3Version, + StemcellOS: newStemcellOS, StemcellVersion: newStemcellVersion, + GitHubRepository: "https://example.com/pomelo", + })) }) It("looks up the correct releases with --update-releases", func() { err := update.Execute([]string{ @@ -241,7 +289,7 @@ var _ = Describe("UpdateStemcell", func() { }) Expect(err).NotTo(HaveOccurred()) - Expect(releaseSource.FindReleaseVersionCallCount()).To(Equal(2)) + Expect(releaseSource.FindReleaseVersionCallCount()).To(Equal(3)) req1, noDownload1 := releaseSource.FindReleaseVersionArgsForCall(0) Expect(req1).To(Equal(cargo.BOSHReleaseTarballSpecification{ @@ -260,8 +308,7 @@ var _ = Describe("UpdateStemcell", func() { Expect(noDownload2).To(BeTrue()) }) - - It("downloads the correct releases", func() { + It("downloads 2 of the 3 correct releases, ", func() { err := update.Execute([]string{ "--kilnfile", kilnfilePath, "--version", newStemcellVersion, "--releases-directory", releasesDirPath, }) @@ -276,6 +323,7 @@ var _ = Describe("UpdateStemcell", func() { Name: release1Name, Version: release1Version, RemotePath: newRelease1RemotePath, RemoteSource: publishableReleaseSourceID, + SHA1: "", }, )) @@ -286,6 +334,7 @@ var _ = Describe("UpdateStemcell", func() { Name: release2Name, Version: release2Version, RemotePath: newRelease2RemotePath, RemoteSource: unpublishableReleaseSourceID, + SHA1: "not-calculated", }, )) }) @@ -390,7 +439,7 @@ var _ = Describe("UpdateStemcell", func() { Version: newStemcellVersion, })) - Expect(updatedLockfile.Releases).To(HaveLen(2)) + Expect(updatedLockfile.Releases).To(HaveLen(3)) Expect(updatedLockfile.Releases).To(ContainElement( cargo.BOSHReleaseTarballLock{ Name: release1Name, @@ -409,6 +458,15 @@ var _ = Describe("UpdateStemcell", func() { RemotePath: newRelease2RemotePath, }, )) + Expect(updatedLockfile.Releases).To(ContainElement( + cargo.BOSHReleaseTarballLock{ + Name: release3Name, + Version: release3Version, + SHA1: newRelease3SHA, + RemoteSource: publishableReleaseSourceID, + RemotePath: newRelease3RemotePath, + }, + )) }) }) diff --git a/internal/component/artifactory_release_source.go b/internal/component/artifactory_release_source.go index 67c5e11d..4d8435b9 100644 --- a/internal/component/artifactory_release_source.go +++ b/internal/component/artifactory_release_source.go @@ -178,13 +178,20 @@ func (ars *ArtifactoryReleaseSource) GetMatchedRelease(spec cargo.BOSHReleaseTar default: return cargo.BOSHReleaseTarballLock{}, fmt.Errorf("unexpected http status: %s", http.StatusText(response.StatusCode)) } - - return cargo.BOSHReleaseTarballLock{ + + matchedRelease := cargo.BOSHReleaseTarballLock{ Name: spec.Name, Version: spec.Version, RemotePath: remotePath, RemoteSource: ars.ID, - }, nil + } + + matchedRelease.SHA1, err = ars.getFileSHA1(matchedRelease) + if err != nil { + return cargo.BOSHReleaseTarballLock{}, err + } + + return matchedRelease, nil } // FindReleaseVersion may use any of the fields on Requirement to return the best matching diff --git a/internal/component/artifactory_release_source_test.go b/internal/component/artifactory_release_source_test.go index 098c771e..2337e5e1 100644 --- a/internal/component/artifactory_release_source_test.go +++ b/internal/component/artifactory_release_source_test.go @@ -106,6 +106,7 @@ var _ = Describe("interacting with BOSH releases on Artifactory", func() { // StemcellVersion: "9.9", RemotePath: "bosh-releases/smoothie/9.9/mango/mango-2.3.4-smoothie-9.9.tgz", RemoteSource: "some-mango-tree", + SHA1: "some-sha", })) }) diff --git a/internal/component/bosh_io_release_source.go b/internal/component/bosh_io_release_source.go index 492a21f8..0260de62 100644 --- a/internal/component/bosh_io_release_source.go +++ b/internal/component/bosh_io_release_source.go @@ -92,13 +92,14 @@ func (src BOSHIOReleaseSource) GetMatchedRelease(requirement cargo.BOSHReleaseTa for _, repo := range repos { for _, suf := range suffixes { fullName := repo + "/" + requirement.Name + suf - exists, err := src.releaseExistOnBoshio(fullName, requirement.Version) + exists, remoteSha, err := src.releaseExistOnBoshio(fullName, requirement.Version) if err != nil { return cargo.BOSHReleaseTarballLock{}, err } if exists { builtRelease := src.createReleaseRemote(requirement, fullName) + builtRelease.SHA1 = remoteSha return builtRelease, nil } } @@ -135,7 +136,7 @@ func (src BOSHIOReleaseSource) FindReleaseVersion(spec cargo.BOSHReleaseTarballS } spec.Version = validReleases[0].Version lock := src.createReleaseRemote(spec, fullName) - lock.SHA1 = validReleases[0].SHA + lock.SHA1 = validReleases[0].SHA1 return lock, nil } } @@ -232,18 +233,18 @@ func (src BOSHIOReleaseSource) getReleases(name string) ([]releaseResponse, erro type releaseResponse struct { Version string `json:"version"` - SHA string `json:"sha1"` + SHA1 string `json:"sha1"` } -func (src BOSHIOReleaseSource) releaseExistOnBoshio(name, version string) (bool, error) { +func (src BOSHIOReleaseSource) releaseExistOnBoshio(name, version string) (bool, string, error) { releaseResponses, err := src.getReleases(name) if err != nil { - return false, err + return false, "", err } for _, rel := range releaseResponses { if rel.Version == version { - return true, nil + return true, rel.SHA1, nil } } - return false, nil + return false, "", nil } diff --git a/internal/component/bosh_io_release_source_test.go b/internal/component/bosh_io_release_source_test.go index a9c7bcc2..447faf46 100644 --- a/internal/component/bosh_io_release_source_test.go +++ b/internal/component/bosh_io_release_source_test.go @@ -47,7 +47,7 @@ var _ = Describe("BOSHIOReleaseSource", func() { testServer.RouteToHandler("GET", path, ghttp.RespondWith(http.StatusOK, `null`)) path, _ = regexp.Compile(`/api/v1/releases/github.com/\S+/uaa.*`) - testServer.RouteToHandler("GET", path, ghttp.RespondWith(http.StatusOK, `[{"version": "73.3.0"}]`)) + testServer.RouteToHandler("GET", path, ghttp.RespondWith(http.StatusOK, `[{"version": "73.3.0", "sha1":"b6e8a9cbc8724edcecb8658fa9459ee6c8fc259e"}]`)) path, _ = regexp.Compile(`/api/v1/releases/github.com/\S+/metrics.*`) testServer.RouteToHandler("GET", path, ghttp.RespondWith(http.StatusOK, `[{"version": "2.3.0"}]`)) @@ -74,6 +74,7 @@ var _ = Describe("BOSHIOReleaseSource", func() { Version: "73.3.0", RemotePath: uaaURL, RemoteSource: component.ReleaseSourceTypeBOSHIO, + SHA1: "b6e8a9cbc8724edcecb8658fa9459ee6c8fc259e", })) foundRelease, err = releaseSource.GetMatchedRelease(rabbitmqRequirement) @@ -299,7 +300,7 @@ var _ = Describe("BOSHIOReleaseSource", func() { testServer = ghttp.NewServer() path, _ := regexp.Compile(`/api/v1/releases/github.com/\S+/cf-rabbitmq.*`) - testServer.RouteToHandler("GET", path, ghttp.RespondWith(http.StatusOK, `[{"name":"github.com/cloudfoundry/cf-rabbitmq-release","version":"309.0.5","url":"https://bosh.io/d/github.com/cloudfoundry/cf-rabbitmq-release?v=309.0.0","sha1":"5df538657c2cc830bda679420a9b162682018ded"},{"name":"github.com/cloudfoundry/cf-rabbitmq-release","version":"308.0.0","url":"https://bosh.io/d/github.com/cloudfoundry/cf-rabbitmq-release?v=308.0.0","sha1":"56202c9a466a8394683ae432ee2dea21ef6ef865"}]`)) + testServer.RouteToHandler("GET", path, ghttp.RespondWith(http.StatusOK, `[{"name":"github.com/cloudfoundry/cf-rabbitmq-release","version":"309.0.5","url":"https://bosh.io/d/github.com/cloudfoundry/cf-rabbitmq-release?v=309.0.0","sha1":"5df538657c2cc830bda679420a9b162682018ded","sha256": "49cad4a9758026cbae7a26f77921300595459dfa6bc0ca5332fc6ba52bd336b8"},{"name":"github.com/cloudfoundry/cf-rabbitmq-release","version":"308.0.0","url":"https://bosh.io/d/github.com/cloudfoundry/cf-rabbitmq-release?v=308.0.0","sha1":"56202c9a466a8394683ae432ee2dea21ef6ef865","sha256":"5970d4211d236896d9366b150a66e38cbbd757fed31895962e499bb5458e0937"}]`)) releaseSource = component.NewBOSHIOReleaseSource(cargo.ReleaseSourceConfig{ID: ID, Publishable: false}, testServer.URL(), logger) })