1package installation_test
2
3import (
4	"errors"
5	"log"
6
7	. "github.com/cloudfoundry/bosh-cli/installation"
8
9	biinstallmanifest "github.com/cloudfoundry/bosh-cli/installation/manifest"
10	mock_registry "github.com/cloudfoundry/bosh-cli/registry/mocks"
11	test_support_mocks "github.com/cloudfoundry/bosh-cli/test_support/mocks"
12	fakebiui "github.com/cloudfoundry/bosh-cli/ui/fakes"
13	boshlog "github.com/cloudfoundry/bosh-utils/logger"
14	"github.com/golang/mock/gomock"
15	. "github.com/onsi/ginkgo"
16	. "github.com/onsi/gomega"
17	"github.com/onsi/gomega/gbytes"
18)
19
20var _ = Describe("Installation", func() {
21	var mockCtrl *gomock.Controller
22
23	BeforeEach(func() {
24		mockCtrl = gomock.NewController(GinkgoT())
25	})
26
27	AfterEach(func() {
28		mockCtrl.Finish()
29	})
30
31	var (
32		manifest                  biinstallmanifest.Manifest
33		mockRegistryServerManager *mock_registry.MockServerManager
34		mockRegistryServer        *mock_registry.MockServer
35
36		target       Target
37		installedJob InstalledJob
38	)
39
40	var newInstalation = func() Installation {
41		return NewInstallation(target, installedJob, manifest, mockRegistryServerManager)
42	}
43
44	BeforeEach(func() {
45		manifest = biinstallmanifest.Manifest{}
46
47		mockRegistryServerManager = mock_registry.NewMockServerManager(mockCtrl)
48		mockRegistryServer = mock_registry.NewMockServer(mockCtrl)
49
50		target = NewTarget("fake-installation-path")
51
52		installedJob = NewInstalledJob(RenderedJobRef{Name: "cpi"}, "fake-job-path")
53	})
54
55	Describe("WithRunningRegistry", func() {
56		var (
57			startCall, spyCall, stopCall *gomock.Call
58			spy                          *test_support_mocks.MockSpy
59			logBuffer                    *gbytes.Buffer
60			logger                       boshlog.Logger
61			fakeStage                    *fakebiui.FakeStage
62		)
63
64		BeforeEach(func() {
65			manifest.Registry = biinstallmanifest.Registry{
66				Username: "fake-username",
67				Password: "fake-password",
68				Host:     "fake-host",
69				Port:     123,
70			}
71
72			spy = test_support_mocks.NewMockSpy(mockCtrl)
73			startCall = mockRegistryServerManager.EXPECT().Start("fake-username", "fake-password", "fake-host", 123).Return(mockRegistryServer, nil)
74			spyCall = spy.EXPECT().Record()
75			stopCall = mockRegistryServer.EXPECT().Stop().Return(nil)
76
77			logBuffer = gbytes.NewBuffer()
78			goLogger := log.New(logBuffer, "", log.LstdFlags)
79			logger = boshlog.New(boshlog.LevelWarn, goLogger)
80			fakeStage = fakebiui.NewFakeStage()
81		})
82
83		It("starts the registry before calling the function", func() {
84			spyCall.After(startCall)
85
86			err := newInstalation().WithRunningRegistry(logger, fakeStage, func() error {
87				spy.Record()
88				return nil
89			})
90			Expect(err).NotTo(HaveOccurred())
91		})
92
93		It("performs stages for starting and stopping the registry", func() {
94			err := newInstalation().WithRunningRegistry(logger, fakeStage, func() error {
95				spy.Record()
96				return nil
97			})
98			Expect(err).NotTo(HaveOccurred())
99
100			Expect(fakeStage.PerformCalls).To(ContainElement(&fakebiui.PerformCall{
101				Name: "Starting registry",
102			}))
103			Expect(fakeStage.PerformCalls).To(ContainElement(&fakebiui.PerformCall{
104				Name: "Stopping registry",
105			}))
106		})
107
108		Context("the function succeeds", func() {
109			It("stops the registry and returns nil", func() {
110				stopCall.After(spyCall)
111
112				err := newInstalation().WithRunningRegistry(logger, fakeStage, func() error {
113					spy.Record()
114					return nil
115				})
116				Expect(err).NotTo(HaveOccurred())
117			})
118		})
119
120		Context("the function fails", func() {
121			It("stops the registry and returns the error", func() {
122				stopCall.After(spyCall)
123				err := newInstalation().WithRunningRegistry(logger, fakeStage, func() error {
124					spy.Record()
125					return errors.New("blarg!")
126				})
127				Expect(err).To(HaveOccurred())
128			})
129		})
130
131		Context("when starting registry fails", func() {
132			It("returns an error and doesn't call the function", func() {
133				startCall.Return(mockRegistryServer, errors.New("registry-start-error"))
134				spyCall.Times(0)
135				stopCall.Times(0)
136
137				err := newInstalation().WithRunningRegistry(logger, fakeStage, func() error {
138					spy.Record()
139					return nil
140				})
141
142				Expect(err).To(HaveOccurred())
143				Expect(err.Error()).To(Equal("Starting registry: registry-start-error"))
144			})
145		})
146
147		Context("when stopping registry fails", func() {
148			Context("when the function fails", func() {
149				It("logs a warning and returns the function error", func() {
150					stopCall.Return(errors.New("registry-stop-error"))
151
152					err := newInstalation().WithRunningRegistry(logger, fakeStage, func() error {
153						spy.Record()
154						return errors.New("blarg!")
155					})
156					Expect(err).To(HaveOccurred())
157					Expect(err.Error()).To(Equal("blarg!"))
158
159					Expect(logBuffer).To(gbytes.Say("registry-stop-error"))
160				})
161			})
162
163			Context("when the function succeeds", func() {
164				It("logs a warning and returns nil", func() {
165					err := newInstalation().WithRunningRegistry(logger, fakeStage, func() error {
166						spy.Record()
167						return nil
168					})
169					Expect(err).NotTo(HaveOccurred())
170				})
171			})
172		})
173	})
174
175	Describe("StartRegistry", func() {
176		Context("when registry config is not empty", func() {
177			BeforeEach(func() {
178				manifest.Registry = biinstallmanifest.Registry{
179					Username: "fake-username",
180					Password: "fake-password",
181					Host:     "fake-host",
182					Port:     123,
183				}
184			})
185
186			It("starts the registry", func() {
187				mockRegistryServerManager.EXPECT().Start("fake-username", "fake-password", "fake-host", 123).Return(mockRegistryServer, nil)
188
189				err := newInstalation().StartRegistry()
190				Expect(err).NotTo(HaveOccurred())
191			})
192
193			Context("when starting registry fails", func() {
194				BeforeEach(func() {
195					mockRegistryServerManager.EXPECT().Start("fake-username", "fake-password", "fake-host", 123).Return(nil, errors.New("fake-registry-start-error"))
196				})
197
198				It("returns an error", func() {
199					err := newInstalation().StartRegistry()
200					Expect(err).To(HaveOccurred())
201					Expect(err.Error()).To(ContainSubstring("fake-registry-start-error"))
202				})
203			})
204		})
205
206		Context("when registry config is empty", func() {
207			BeforeEach(func() {
208				manifest.Registry = biinstallmanifest.Registry{}
209			})
210
211			It("does not start the registry", func() {
212				err := newInstalation().StartRegistry()
213				Expect(err).ToNot(HaveOccurred())
214			})
215		})
216	})
217
218	Describe("StopRegistry", func() {
219		Context("when registry has been started", func() {
220			var installation Installation
221
222			BeforeEach(func() {
223				manifest.Registry = biinstallmanifest.Registry{
224					Username: "fake-username",
225					Password: "fake-password",
226					Host:     "fake-host",
227					Port:     123,
228				}
229
230				installation = newInstalation()
231
232				mockRegistryServerManager.EXPECT().Start("fake-username", "fake-password", "fake-host", 123).Return(mockRegistryServer, nil)
233				err := installation.StartRegistry()
234				Expect(err).ToNot(HaveOccurred())
235			})
236
237			It("stops the registry", func() {
238				mockRegistryServer.EXPECT().Stop()
239
240				err := installation.StopRegistry()
241				Expect(err).NotTo(HaveOccurred())
242			})
243		})
244
245		Context("when registry is configured but has not been started", func() {
246			BeforeEach(func() {
247				manifest.Registry = biinstallmanifest.Registry{
248					Username: "fake-username",
249					Password: "fake-password",
250					Host:     "fake-host",
251					Port:     123,
252				}
253			})
254
255			It("returns an error", func() {
256				err := newInstalation().StopRegistry()
257				Expect(err).To(HaveOccurred())
258				Expect(err.Error()).To(ContainSubstring("Registry must be started before it can be stopped"))
259			})
260		})
261
262		Context("when registry config is empty", func() {
263			BeforeEach(func() {
264				manifest.Registry = biinstallmanifest.Registry{}
265			})
266
267			It("does not stop the registry", func() {
268				err := newInstalation().StopRegistry()
269				Expect(err).ToNot(HaveOccurred())
270			})
271		})
272	})
273})
274