From cc107027baa6b5eb0c2ab034e8eed08ccd242c16 Mon Sep 17 00:00:00 2001 From: dmitriy kalinin Date: Tue, 20 Sep 2016 12:17:48 -0700 Subject: [PATCH] move tests from cmd/deploy to cmd/release_manager --- bin/gen-fakes | 1 + cmd/deploy_test.go | 208 ++++++++--------------------- cmd/fakes/fake_release_uploader.go | 55 ++++++++ cmd/release_manager_test.go | 184 +++++++++++++++++++++++++ cmd/update_runtime_config_test.go | 85 ++++-------- 5 files changed, 318 insertions(+), 215 deletions(-) create mode 100644 cmd/fakes/fake_release_uploader.go create mode 100644 cmd/release_manager_test.go diff --git a/bin/gen-fakes b/bin/gen-fakes index c1df486fe..93f5da485 100755 --- a/bin/gen-fakes +++ b/bin/gen-fakes @@ -10,6 +10,7 @@ counterfeiter cmd Downloader counterfeiter cmd LoginStrategy counterfeiter cmd ReleaseUploadingCmd counterfeiter cmd ReleaseCreatingCmd +counterfeiter cmd ReleaseUploader counterfeiter cmd/config Config counterfeiter deployment/manifest Parser diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index 442e6a285..bfb695809 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -4,7 +4,6 @@ import ( "errors" "github.com/cppforlife/go-patch/patch" - semver "github.com/cppforlife/go-semi-semantic/version" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -13,18 +12,15 @@ import ( boshdir "github.com/cloudfoundry/bosh-cli/director" fakedir "github.com/cloudfoundry/bosh-cli/director/fakes" boshtpl "github.com/cloudfoundry/bosh-cli/director/template" - boshrel "github.com/cloudfoundry/bosh-cli/release" - fakerel "github.com/cloudfoundry/bosh-cli/release/fakes" fakeui "github.com/cloudfoundry/bosh-cli/ui/fakes" ) var _ = Describe("DeployCmd", func() { var ( - ui *fakeui.FakeUI - deployment *fakedir.FakeDeployment - uploadReleaseCmd *fakecmd.FakeReleaseUploadingCmd - createReleaseCmd *fakecmd.FakeReleaseCreatingCmd - command DeployCmd + ui *fakeui.FakeUI + deployment *fakedir.FakeDeployment + releaseUploader *fakecmd.FakeReleaseUploader + command DeployCmd ) BeforeEach(func() { @@ -33,20 +29,11 @@ var _ = Describe("DeployCmd", func() { NameStub: func() string { return "dep" }, } - uploadReleaseCmd = &fakecmd.FakeReleaseUploadingCmd{} - - createReleaseCmd = &fakecmd.FakeReleaseCreatingCmd{ - RunStub: func(opts CreateReleaseOpts) (boshrel.Release, error) { - release := &fakerel.FakeRelease{ - NameStub: func() string { return opts.Name }, - VersionStub: func() string { return opts.Name + "-created-ver" }, - } - return release, nil - }, + releaseUploader = &fakecmd.FakeReleaseUploader{ + UploadReleasesStub: func(bytes []byte) ([]byte, error) { return bytes, nil }, } - releaseManager := NewReleaseManager(createReleaseCmd, uploadReleaseCmd) - command = NewDeployCmd(ui, deployment, releaseManager) + command = NewDeployCmd(ui, deployment, releaseUploader) }) Describe("Run", func() { @@ -138,57 +125,30 @@ var _ = Describe("DeployCmd", func() { Expect(deployment.UpdateCallCount()).To(Equal(0)) }) - It("creates and uploads releases but does not deploy if confirmation is rejected", func() { + It("uploads releases provided in the manifest after manifest has been interpolated", func() { opts.Args.Manifest = FileBytesArg{ - Bytes: []byte(` -name: dep -releases: -- name: capi - sha1: capi-sha1 - url: /capi-url - version: create -`), + Bytes: []byte("name: dep\nbefore-upload-manifest: ((key))"), } - ui.AskedConfirmationErr = errors.New("stop") - - err := act() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("stop")) - - Expect(createReleaseCmd.RunCallCount()).To(Equal(1)) - Expect(uploadReleaseCmd.RunCallCount()).To(Equal(1)) - Expect(deployment.UpdateCallCount()).To(Equal(0)) - }) + opts.VarKVs = []boshtpl.VarKV{ + {Name: "key", Value: "key-val"}, + } - It("returns an error if diffing failed", func() { - deployment.DiffReturns(boshdir.DiffLines{}, errors.New("Fetching diff result")) + releaseUploader.UploadReleasesReturns([]byte("after-upload-manifest"), nil) err := act() - Expect(err).To(HaveOccurred()) - }) + Expect(err).ToNot(HaveOccurred()) - It("gets the diff from the deployment", func() { - expectedDiff := boshdir.DiffLines{ - []interface{}{ - "some line that stayed", nil, - }, []interface{}{ - "some line that was added", "added", - }, []interface{}{ - "some line that was removed", "removed", - }, - } + bytes := releaseUploader.UploadReleasesArgsForCall(0) + Expect(bytes).To(Equal([]byte("before-upload-manifest: key-val\nname: dep\n"))) - deployment.DiffReturns(expectedDiff, nil) - err := act() - Expect(err).ToNot(HaveOccurred()) - Expect(deployment.DiffCallCount()).To(Equal(1)) - Expect(ui.Said).To(ContainElement(" some line that stayed\n")) - Expect(ui.Said).To(ContainElement("+ some line that was added\n")) - Expect(ui.Said).To(ContainElement("- some line that was removed\n")) + Expect(deployment.UpdateCallCount()).To(Equal(1)) + + bytes, _ = deployment.UpdateArgsForCall(0) + Expect(bytes).To(Equal([]byte("after-upload-manifest"))) }) - It("uploads remote releases skipping releases without url", func() { + It("returns error and does not deploy if uploading releases fails", func() { opts.Args.Manifest = FileBytesArg{ Bytes: []byte(` name: dep @@ -197,129 +157,65 @@ releases: sha1: capi-sha1 url: https://capi-url version: 1+capi -- name: rel-without-upload - version: 1+rel -- name: consul - sha1: consul-sha1 - url: https://consul-url - version: 1+consul -- name: local - url: file:///local-dir - version: create `), } - err := act() - Expect(err).ToNot(HaveOccurred()) - - Expect(uploadReleaseCmd.RunCallCount()).To(Equal(3)) - - Expect(uploadReleaseCmd.RunArgsForCall(0)).To(Equal(UploadReleaseOpts{ - Name: "capi", - Args: UploadReleaseArgs{URL: URLArg("https://capi-url")}, - SHA1: "capi-sha1", - Version: VersionArg(semver.MustNewVersionFromString("1+capi")), - })) + releaseUploader.UploadReleasesReturns(nil, errors.New("fake-err")) - Expect(uploadReleaseCmd.RunArgsForCall(1)).To(Equal(UploadReleaseOpts{ - Name: "consul", - Args: UploadReleaseArgs{URL: URLArg("https://consul-url")}, - SHA1: "consul-sha1", - Version: VersionArg(semver.MustNewVersionFromString("1+consul")), - })) + err := act() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("fake-err")) - arg := uploadReleaseCmd.RunArgsForCall(2) - Expect(arg.Release.Name()).To(Equal("local")) - Expect(arg).To(Equal(UploadReleaseOpts{Release: arg.Release})) // only Release should be set + Expect(deployment.UpdateCallCount()).To(Equal(0)) }) - It("creates releases if version is 'create' skipping others", func() { + It("uploads releases but does not deploy if confirmation is rejected", func() { opts.Args.Manifest = FileBytesArg{ Bytes: []byte(` name: dep releases: - name: capi - url: file:///capi-dir - version: create -- name: rel-without-upload - version: 1+rel -- name: consul - url: /consul-dir # doesn't require file:// + sha1: capi-sha1 + url: /capi-url version: create `), } - err := act() - Expect(err).ToNot(HaveOccurred()) - - Expect(createReleaseCmd.RunCallCount()).To(Equal(2)) - - Expect(createReleaseCmd.RunArgsForCall(0)).To(Equal(CreateReleaseOpts{ - Name: "capi", - Directory: DirOrCWDArg{Path: "/capi-dir"}, - TimestampVersion: true, - Force: true, - })) + ui.AskedConfirmationErr = errors.New("stop") - Expect(createReleaseCmd.RunArgsForCall(1)).To(Equal(CreateReleaseOpts{ - Name: "consul", - Directory: DirOrCWDArg{Path: "/consul-dir"}, - TimestampVersion: true, - Force: true, - })) + err := act() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("stop")) - bytes, _ := deployment.UpdateArgsForCall(0) - Expect(bytes).To(Equal([]byte(`name: dep -releases: -- name: capi - url: file:///capi-dir - version: capi-created-ver -- name: rel-without-upload - version: 1+rel -- name: consul - url: /consul-dir - version: consul-created-ver -`))) + Expect(releaseUploader.UploadReleasesCallCount()).To(Equal(1)) + Expect(deployment.UpdateCallCount()).To(Equal(0)) }) - It("returns error and does not deploy if uploading release fails", func() { - opts.Args.Manifest = FileBytesArg{ - Bytes: []byte(` -name: dep -releases: -- name: capi - sha1: capi-sha1 - url: https://capi-url - version: 1+capi -`), - } - uploadReleaseCmd.RunReturns(errors.New("fake-err")) + It("returns an error if diffing failed", func() { + deployment.DiffReturns(boshdir.DiffLines{}, errors.New("Fetching diff result")) err := act() Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("fake-err")) - - Expect(deployment.UpdateCallCount()).To(Equal(0)) }) - It("returns an error if release version cannot be parsed", func() { - opts.Args.Manifest = FileBytesArg{ - Bytes: []byte(` -name: dep -releases: -- name: capi - sha1: capi-sha1 - url: https://capi-url - version: 1+capi+capi -`), + It("gets the diff from the deployment", func() { + expectedDiff := boshdir.DiffLines{ + []interface{}{ + "some line that stayed", nil, + }, []interface{}{ + "some line that was added", "added", + }, []interface{}{ + "some line that was removed", "removed", + }, } + deployment.DiffReturns(expectedDiff, nil) err := act() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Expected version '1+capi+capi' to match version format")) - - Expect(uploadReleaseCmd.RunCallCount()).To(Equal(0)) - Expect(deployment.UpdateCallCount()).To(Equal(0)) + Expect(err).ToNot(HaveOccurred()) + Expect(deployment.DiffCallCount()).To(Equal(1)) + Expect(ui.Said).To(ContainElement(" some line that stayed\n")) + Expect(ui.Said).To(ContainElement("+ some line that was added\n")) + Expect(ui.Said).To(ContainElement("- some line that was removed\n")) }) It("returns error if deploying failed", func() { diff --git a/cmd/fakes/fake_release_uploader.go b/cmd/fakes/fake_release_uploader.go new file mode 100644 index 000000000..f3ff4dd24 --- /dev/null +++ b/cmd/fakes/fake_release_uploader.go @@ -0,0 +1,55 @@ +// This file was generated by counterfeiter +package fakes + +import ( + "sync" + + "github.com/cloudfoundry/bosh-cli/cmd" +) + +type FakeReleaseUploader struct { + UploadReleasesStub func([]byte) ([]byte, error) + uploadReleasesMutex sync.RWMutex + uploadReleasesArgsForCall []struct { + arg1 []byte + } + uploadReleasesReturns struct { + result1 []byte + result2 error + } +} + +func (fake *FakeReleaseUploader) UploadReleases(arg1 []byte) ([]byte, error) { + fake.uploadReleasesMutex.Lock() + fake.uploadReleasesArgsForCall = append(fake.uploadReleasesArgsForCall, struct { + arg1 []byte + }{arg1}) + fake.uploadReleasesMutex.Unlock() + if fake.UploadReleasesStub != nil { + return fake.UploadReleasesStub(arg1) + } else { + return fake.uploadReleasesReturns.result1, fake.uploadReleasesReturns.result2 + } +} + +func (fake *FakeReleaseUploader) UploadReleasesCallCount() int { + fake.uploadReleasesMutex.RLock() + defer fake.uploadReleasesMutex.RUnlock() + return len(fake.uploadReleasesArgsForCall) +} + +func (fake *FakeReleaseUploader) UploadReleasesArgsForCall(i int) []byte { + fake.uploadReleasesMutex.RLock() + defer fake.uploadReleasesMutex.RUnlock() + return fake.uploadReleasesArgsForCall[i].arg1 +} + +func (fake *FakeReleaseUploader) UploadReleasesReturns(result1 []byte, result2 error) { + fake.UploadReleasesStub = nil + fake.uploadReleasesReturns = struct { + result1 []byte + result2 error + }{result1, result2} +} + +var _ cmd.ReleaseUploader = new(FakeReleaseUploader) diff --git a/cmd/release_manager_test.go b/cmd/release_manager_test.go new file mode 100644 index 000000000..545b65e7d --- /dev/null +++ b/cmd/release_manager_test.go @@ -0,0 +1,184 @@ +package cmd_test + +import ( + "errors" + + semver "github.com/cppforlife/go-semi-semantic/version" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + . "github.com/cloudfoundry/bosh-cli/cmd" + fakecmd "github.com/cloudfoundry/bosh-cli/cmd/fakes" + boshrel "github.com/cloudfoundry/bosh-cli/release" + fakerel "github.com/cloudfoundry/bosh-cli/release/fakes" +) + +var _ = Describe("ReleaseManager", func() { + var ( + createReleaseCmd *fakecmd.FakeReleaseCreatingCmd + uploadReleaseCmd *fakecmd.FakeReleaseUploadingCmd + releaseManager ReleaseManager + ) + + BeforeEach(func() { + createReleaseCmd = &fakecmd.FakeReleaseCreatingCmd{ + RunStub: func(opts CreateReleaseOpts) (boshrel.Release, error) { + release := &fakerel.FakeRelease{ + NameStub: func() string { return opts.Name }, + VersionStub: func() string { return opts.Name + "-created-ver" }, + } + return release, nil + }, + } + + uploadReleaseCmd = &fakecmd.FakeReleaseUploadingCmd{} + + releaseManager = NewReleaseManager(createReleaseCmd, uploadReleaseCmd) + }) + + Describe("UploadReleases", func() { + It("uploads remote releases skipping releases without url", func() { + bytes := []byte(` +releases: +- name: capi + sha1: capi-sha1 + url: https://capi-url + version: 1+capi +- name: rel-without-upload + version: 1+rel +- name: consul + sha1: consul-sha1 + url: https://consul-url + version: 1+consul +- name: local + url: file:///local-dir + version: create +`) + + _, err := releaseManager.UploadReleases(bytes) + Expect(err).ToNot(HaveOccurred()) + + Expect(uploadReleaseCmd.RunCallCount()).To(Equal(3)) + + Expect(uploadReleaseCmd.RunArgsForCall(0)).To(Equal(UploadReleaseOpts{ + Name: "capi", + Args: UploadReleaseArgs{URL: URLArg("https://capi-url")}, + SHA1: "capi-sha1", + Version: VersionArg(semver.MustNewVersionFromString("1+capi")), + })) + + Expect(uploadReleaseCmd.RunArgsForCall(1)).To(Equal(UploadReleaseOpts{ + Name: "consul", + Args: UploadReleaseArgs{URL: URLArg("https://consul-url")}, + SHA1: "consul-sha1", + Version: VersionArg(semver.MustNewVersionFromString("1+consul")), + })) + + arg := uploadReleaseCmd.RunArgsForCall(2) + Expect(arg.Release.Name()).To(Equal("local")) + Expect(arg).To(Equal(UploadReleaseOpts{Release: arg.Release})) // only Release should be set + }) + + It("creates releases if version is 'create' skipping others", func() { + bytes := []byte(` +releases: +- name: capi + url: file:///capi-dir + version: create +- name: rel-without-upload + version: 1+rel +- name: consul + url: /consul-dir # doesn't require file:// + version: create +`) + + bytes, err := releaseManager.UploadReleases(bytes) + Expect(err).ToNot(HaveOccurred()) + + Expect(createReleaseCmd.RunCallCount()).To(Equal(2)) + + Expect(createReleaseCmd.RunArgsForCall(0)).To(Equal(CreateReleaseOpts{ + Name: "capi", + Directory: DirOrCWDArg{Path: "/capi-dir"}, + TimestampVersion: true, + Force: true, + })) + + Expect(createReleaseCmd.RunArgsForCall(1)).To(Equal(CreateReleaseOpts{ + Name: "consul", + Directory: DirOrCWDArg{Path: "/consul-dir"}, + TimestampVersion: true, + Force: true, + })) + + Expect(bytes).To(Equal([]byte(`releases: +- name: capi + url: file:///capi-dir + version: capi-created-ver +- name: rel-without-upload + version: 1+rel +- name: consul + url: /consul-dir + version: consul-created-ver +`))) + }) + + It("returns error and does not upload if creating release fails", func() { + bytes := []byte(` +releases: +- name: capi + url: file:///capi-dir + version: create +`) + createReleaseCmd.RunReturns(nil, errors.New("fake-err")) + + _, err := releaseManager.UploadReleases(bytes) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("fake-err")) + + Expect(uploadReleaseCmd.RunCallCount()).To(Equal(0)) + }) + + It("returns error if uploading release fails", func() { + bytes := []byte(` +releases: +- name: capi + sha1: capi-sha1 + url: https://capi-url + version: 1+capi +`) + uploadReleaseCmd.RunReturns(errors.New("fake-err")) + + _, err := releaseManager.UploadReleases(bytes) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("fake-err")) + }) + + It("returns an error and does not upload if release version cannot be parsed", func() { + bytes := []byte(` +releases: +- name: capi + sha1: capi-sha1 + url: https://capi-url + version: 1+capi+capi +`) + + _, err := releaseManager.UploadReleases(bytes) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Expected version '1+capi+capi' to match version format")) + + Expect(uploadReleaseCmd.RunCallCount()).To(Equal(0)) + }) + + It("returns an error if bytes cannot be parsed to find releases", func() { + bytes := []byte(`-`) + + _, err := releaseManager.UploadReleases(bytes) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Parsing manifest")) + + Expect(createReleaseCmd.RunCallCount()).To(Equal(0)) + Expect(uploadReleaseCmd.RunCallCount()).To(Equal(0)) + }) + }) +}) diff --git a/cmd/update_runtime_config_test.go b/cmd/update_runtime_config_test.go index 2ba53ad92..1560986af 100644 --- a/cmd/update_runtime_config_test.go +++ b/cmd/update_runtime_config_test.go @@ -4,7 +4,6 @@ import ( "errors" "github.com/cppforlife/go-patch/patch" - semver "github.com/cppforlife/go-semi-semantic/version" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -17,18 +16,19 @@ import ( var _ = Describe("UpdateRuntimeConfigCmd", func() { var ( - ui *fakeui.FakeUI - director *fakedir.FakeDirector - uploadReleaseCmd *fakecmd.FakeReleaseUploadingCmd - command UpdateRuntimeConfigCmd + ui *fakeui.FakeUI + director *fakedir.FakeDirector + releaseUploader *fakecmd.FakeReleaseUploader + command UpdateRuntimeConfigCmd ) BeforeEach(func() { ui = &fakeui.FakeUI{} director = &fakedir.FakeDirector{} - uploadReleaseCmd = &fakecmd.FakeReleaseUploadingCmd{} - releaseManager := NewReleaseManager(nil, uploadReleaseCmd) - command = NewUpdateRuntimeConfigCmd(ui, director, releaseManager) + releaseUploader = &fakecmd.FakeReleaseUploader{ + UploadReleasesStub: func(bytes []byte) ([]byte, error) { return bytes, nil }, + } + command = NewUpdateRuntimeConfigCmd(ui, director, releaseUploader) }) Describe("Run", func() { @@ -87,79 +87,46 @@ var _ = Describe("UpdateRuntimeConfigCmd", func() { Expect(bytes).To(Equal([]byte("name1: val1-from-kv\nname2: val2-from-file\nxyz: val\n"))) }) - It("uploads remote releases skipping releases without url", func() { + It("uploads releases provided in the manifest after manifest has been interpolated", func() { opts.Args.RuntimeConfig = FileBytesArg{ - Bytes: []byte(` -releases: -- name: capi - sha1: capi-sha1 - url: https://capi-url - version: 1+capi -- name: rel-without-upload - version: 1+rel -- name: consul - sha1: consul-sha1 - url: https://consul-url - version: 1+consul -`), + Bytes: []byte("before-upload-config: ((key))"), } + opts.VarKVs = []boshtpl.VarKV{ + {Name: "key", Value: "key-val"}, + } + + releaseUploader.UploadReleasesReturns([]byte("after-upload-config"), nil) + err := act() Expect(err).ToNot(HaveOccurred()) - Expect(uploadReleaseCmd.RunCallCount()).To(Equal(2)) - - Expect(uploadReleaseCmd.RunArgsForCall(0)).To(Equal(UploadReleaseOpts{ - Name: "capi", - Args: UploadReleaseArgs{URL: URLArg("https://capi-url")}, - SHA1: "capi-sha1", - Version: VersionArg(semver.MustNewVersionFromString("1+capi")), - })) - - Expect(uploadReleaseCmd.RunArgsForCall(1)).To(Equal(UploadReleaseOpts{ - Name: "consul", - Args: UploadReleaseArgs{URL: URLArg("https://consul-url")}, - SHA1: "consul-sha1", - Version: VersionArg(semver.MustNewVersionFromString("1+consul")), - })) - }) - - It("returns error and does not deploy if uploading release fails", func() { - opts.Args.RuntimeConfig = FileBytesArg{ - Bytes: []byte(` -releases: -- name: capi - sha1: capi-sha1 - url: https://capi-url - version: 1+capi -`), - } - uploadReleaseCmd.RunReturns(errors.New("fake-err")) + bytes := releaseUploader.UploadReleasesArgsForCall(0) + Expect(bytes).To(Equal([]byte("before-upload-config: key-val\n"))) - err := act() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("fake-err")) + Expect(director.UpdateRuntimeConfigCallCount()).To(Equal(1)) - Expect(director.UpdateRuntimeConfigCallCount()).To(Equal(0)) + bytes = director.UpdateRuntimeConfigArgsForCall(0) + Expect(bytes).To(Equal([]byte("after-upload-config"))) }) - It("returns an error if release version cannot be parsed", func() { + It("returns error and does not deploy if uploading releases fails", func() { opts.Args.RuntimeConfig = FileBytesArg{ Bytes: []byte(` -name: dep releases: - name: capi sha1: capi-sha1 url: https://capi-url - version: 1+capi+capi + version: 1+capi `), } + releaseUploader.UploadReleasesReturns(nil, errors.New("fake-err")) + err := act() Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Expected version '1+capi+capi' to match version format")) + Expect(err.Error()).To(ContainSubstring("fake-err")) - Expect(uploadReleaseCmd.RunCallCount()).To(Equal(0)) Expect(director.UpdateRuntimeConfigCallCount()).To(Equal(0)) })