}) }) Describe("Alert", func() { itAdaptsMessage := func(msgContent, expectedTitle string) { sshMsg := boshsyslog.Msg{Content: msgContent} sshAdapter := NewSSHAdapter( sshMsg, settingsService, uuidGenerator, timeService, logger, ) uuidGenerator.GeneratedUUID = "fake-uuid" builtAlert, err := sshAdapter.Alert() Expect(err).ToNot(HaveOccurred()) Expect(builtAlert.Title).To(Equal(expectedTitle)) Expect(builtAlert.ID).To(Equal("fake-uuid")) Expect(builtAlert.Severity).To(Equal(SeverityWarning)) Expect(builtAlert.Summary).To(Equal(msgContent)) Expect(builtAlert.CreatedAt).To(Equal(timeService.Now().Unix())) } It("Returns logout when the user disconnects", func() { itAdaptsMessage("Received disconnect from 9.9.9.9: 11: disconnected by user", "SSH Logout") }) It("Returns login when login is successful (publickey)", func() {
Expect(err).ToNot(HaveOccurred()) fileName := file.Name() defer fs.RemoveAll(fileName) err = blobstore.CleanUp(fileName) Expect(err).ToNot(HaveOccurred()) Expect(fs.FileExists(fileName)).To(BeFalse()) }) }) Describe("Create", func() { It("creates the local blob", func() { fs.WriteFileString("/fake-file.txt", "fake-file-contents") uuidGen.GeneratedUUID = "some-uuid" blobID, fingerprint, err := blobstore.Create("/fake-file.txt") Expect(err).ToNot(HaveOccurred()) Expect(blobID).To(Equal("some-uuid")) Expect(fingerprint).To(BeEmpty()) dirStats := fs.GetFileTestStat(fakeBlobstorePath) Expect(dirStats).ToNot(BeNil()) Expect(dirStats.FileMode).To(Equal(os.FileMode(0770))) writtenFileStats := fs.GetFileTestStat(fakeBlobstorePath + "/some-uuid") Expect(writtenFileStats).ToNot(BeNil()) Expect("fake-file-contents").To(Equal(writtenFileStats.StringContents())) })
func init() { Describe("asyncTaskService", func() { var ( uuidGen *fakeuuid.FakeGenerator service Service ) BeforeEach(func() { uuidGen = &fakeuuid.FakeGenerator{} service = NewAsyncTaskService(uuidGen, boshlog.NewLogger(boshlog.LevelNone)) }) Describe("StartTask", func() { startAndWaitForTaskCompletion := func(task Task) Task { service.StartTask(task) for task.State == StateRunning { time.Sleep(time.Nanosecond) task, _ = service.FindTaskWithID(task.ID) } return task } It("sets return value on a successful task", func() { runFunc := func() (interface{}, error) { return 123, nil } task, err := service.CreateTask(runFunc, nil, nil) Expect(err).ToNot(HaveOccurred()) task = startAndWaitForTaskCompletion(task) Expect(task.State).To(BeEquivalentTo(StateDone)) Expect(task.Value).To(Equal(123)) Expect(task.Error).To(BeNil()) }) It("sets task error on a failing task", func() { err := errors.New("fake-error") runFunc := func() (interface{}, error) { return nil, err } task, createErr := service.CreateTask(runFunc, nil, nil) Expect(createErr).ToNot(HaveOccurred()) task = startAndWaitForTaskCompletion(task) Expect(task.State).To(BeEquivalentTo(StateFailed)) Expect(task.Value).To(BeNil()) Expect(task.Error).To(Equal(err)) }) Describe("CreateTask", func() { It("can run task created with CreateTask which does not have end func", func() { ranFunc := false runFunc := func() (interface{}, error) { ranFunc = true; return nil, nil } task, err := service.CreateTask(runFunc, nil, nil) Expect(err).ToNot(HaveOccurred()) startAndWaitForTaskCompletion(task) Expect(ranFunc).To(BeTrue()) }) It("can run task created with CreateTask which has end func", func() { ranFunc := false runFunc := func() (interface{}, error) { ranFunc = true; return nil, nil } ranEndFunc := false endFunc := func(Task) { ranEndFunc = true } task, err := service.CreateTask(runFunc, nil, endFunc) Expect(err).ToNot(HaveOccurred()) startAndWaitForTaskCompletion(task) Expect(ranFunc).To(BeTrue()) Expect(ranEndFunc).To(BeTrue()) }) It("returns an error if generate uuid fails", func() { uuidGen.GenerateError = errors.New("fake-generate-uuid-error") _, err := service.CreateTask(nil, nil, nil) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-generate-uuid-error")) }) }) Describe("CreateTaskWithID", func() { It("can run task created with CreateTaskWithID which does not have end func", func() { ranFunc := false runFunc := func() (interface{}, error) { ranFunc = true; return nil, nil } task := service.CreateTaskWithID("fake-task-id", runFunc, nil, nil) startAndWaitForTaskCompletion(task) Expect(ranFunc).To(BeTrue()) }) It("can run task created with CreateTaskWithID which has end func", func() { ranFunc := false runFunc := func() (interface{}, error) { ranFunc = true; return nil, nil } ranEndFunc := false endFunc := func(Task) { ranEndFunc = true } task := service.CreateTaskWithID("fake-task-id", runFunc, nil, endFunc) startAndWaitForTaskCompletion(task) Expect(ranFunc).To(BeTrue()) Expect(ranEndFunc).To(BeTrue()) }) }) It("can process many tasks simultaneously", func() { taskFunc := func() (interface{}, error) { time.Sleep(10 * time.Millisecond) return nil, nil } ids := []string{} for id := 1; id < 200; id++ { idStr := fmt.Sprintf("%d", id) uuidGen.GeneratedUUID = idStr ids = append(ids, idStr) task, err := service.CreateTask(taskFunc, nil, nil) Expect(err).ToNot(HaveOccurred()) go service.StartTask(task) } for { allDone := true for _, id := range ids { task, _ := service.FindTaskWithID(id) if task.State != StateDone { allDone = false break } } if allDone { break } time.Sleep(200 * time.Millisecond) } }) }) Describe("CreateTask", func() { It("creates a task with auto-assigned id", func() { uuidGen.GeneratedUUID = "fake-uuid" runFuncCalled := false runFunc := func() (interface{}, error) { runFuncCalled = true return nil, nil } cancelFuncCalled := false cancelFunc := func(_ Task) error { cancelFuncCalled = true return nil } endFuncCalled := false endFunc := func(_ Task) { endFuncCalled = true } task, err := service.CreateTask(runFunc, cancelFunc, endFunc) Expect(err).ToNot(HaveOccurred()) Expect(task.ID).To(Equal("fake-uuid")) Expect(task.State).To(Equal(StateRunning)) task.Func() Expect(runFuncCalled).To(BeTrue()) task.CancelFunc(task) Expect(cancelFuncCalled).To(BeTrue()) task.EndFunc(task) Expect(endFuncCalled).To(BeTrue()) }) }) Describe("CreateTaskWithID", func() { It("creates a task with given id", func() { runFuncCalled := false runFunc := func() (interface{}, error) { runFuncCalled = true return nil, nil } cancelFuncCalled := false cancelFunc := func(_ Task) error { cancelFuncCalled = true return nil } endFuncCalled := false endFunc := func(_ Task) { endFuncCalled = true } task := service.CreateTaskWithID("fake-task-id", runFunc, cancelFunc, endFunc) Expect(task.ID).To(Equal("fake-task-id")) Expect(task.State).To(Equal(StateRunning)) task.Func() Expect(runFuncCalled).To(BeTrue()) task.CancelFunc(task) Expect(cancelFuncCalled).To(BeTrue()) task.EndFunc(task) Expect(endFuncCalled).To(BeTrue()) }) }) }) }
func init() { Describe("Agent", func() { var ( logger boshlog.Logger handler *fakembus.FakeHandler platform *fakeplatform.FakePlatform actionDispatcher *fakeagent.FakeActionDispatcher jobSupervisor *fakejobsuper.FakeJobSupervisor specService *fakeas.FakeV1Service syslogServer *fakesyslog.FakeServer settingsService *fakesettings.FakeSettingsService uuidGenerator *fakeuuid.FakeGenerator timeService *fakeclock.FakeClock agent Agent ) BeforeEach(func() { logger = boshlog.NewLogger(boshlog.LevelNone) handler = &fakembus.FakeHandler{} platform = fakeplatform.NewFakePlatform() actionDispatcher = &fakeagent.FakeActionDispatcher{} jobSupervisor = fakejobsuper.NewFakeJobSupervisor() specService = fakeas.NewFakeV1Service() syslogServer = &fakesyslog.FakeServer{} settingsService = &fakesettings.FakeSettingsService{} uuidGenerator = &fakeuuid.FakeGenerator{} timeService = fakeclock.NewFakeClock(time.Now()) agent = New( logger, handler, platform, actionDispatcher, jobSupervisor, specService, syslogServer, 5*time.Millisecond, settingsService, uuidGenerator, timeService, ) }) Describe("Run", func() { It("lets dispatcher handle requests arriving via handler", func() { err := agent.Run() Expect(err).ToNot(HaveOccurred()) expectedResp := boshhandler.NewValueResponse("pong") actionDispatcher.DispatchResp = expectedResp req := boshhandler.NewRequest("fake-reply", "fake-action", []byte("fake-payload")) resp := handler.RunFunc(req) Expect(actionDispatcher.DispatchReq).To(Equal(req)) Expect(resp).To(Equal(expectedResp)) }) It("resumes persistent actions *before* dispatching new requests", func() { resumedBeforeStartingToDispatch := false handler.RunCallBack = func() { resumedBeforeStartingToDispatch = actionDispatcher.ResumedPreviouslyDispatchedTasks } err := agent.Run() Expect(err).ToNot(HaveOccurred()) Expect(resumedBeforeStartingToDispatch).To(BeTrue()) }) Context("when heartbeats can be sent", func() { BeforeEach(func() { handler.KeepOnRunning() }) BeforeEach(func() { jobName := "fake-job" jobIndex := 1 specService.Spec = boshas.V1ApplySpec{ JobSpec: boshas.JobSpec{Name: &jobName}, Index: &jobIndex, } jobSupervisor.StatusStatus = "fake-state" platform.FakeVitalsService.GetVitals = boshvitals.Vitals{ Load: []string{"a", "b", "c"}, } }) expectedJobName := "fake-job" expectedJobIndex := 1 expectedHb := Heartbeat{ Job: &expectedJobName, Index: &expectedJobIndex, JobState: "fake-state", Vitals: boshvitals.Vitals{Load: []string{"a", "b", "c"}}, } It("sends initial heartbeat", func() { // Configure periodic heartbeat every 5 hours // so that we are sure that we will not receive it agent = New( logger, handler, platform, actionDispatcher, jobSupervisor, specService, syslogServer, 5*time.Hour, settingsService, uuidGenerator, timeService, ) // Immediately exit after sending initial heartbeat handler.SendErr = errors.New("stop") err := agent.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("stop")) Expect(handler.SendInputs()).To(Equal([]fakembus.SendInput{ { Target: boshhandler.HealthMonitor, Topic: boshhandler.Heartbeat, Message: expectedHb, }, })) }) It("sends periodic heartbeats", func() { sentRequests := 0 handler.SendCallback = func(_ fakembus.SendInput) { sentRequests++ if sentRequests == 3 { handler.SendErr = errors.New("stop") } } err := agent.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("stop")) Expect(handler.SendInputs()).To(Equal([]fakembus.SendInput{ { Target: boshhandler.HealthMonitor, Topic: boshhandler.Heartbeat, Message: expectedHb, }, { Target: boshhandler.HealthMonitor, Topic: boshhandler.Heartbeat, Message: expectedHb, }, { Target: boshhandler.HealthMonitor, Topic: boshhandler.Heartbeat, Message: expectedHb, }, })) }) }) Context("when the agent fails to get job spec for a heartbeat", func() { BeforeEach(func() { specService.GetErr = errors.New("fake-spec-service-error") handler.KeepOnRunning() }) It("returns the error", func() { err := agent.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-spec-service-error")) }) }) Context("when the agent fails to get vitals for a heartbeat", func() { BeforeEach(func() { platform.FakeVitalsService.GetErr = errors.New("fake-vitals-service-error") handler.KeepOnRunning() }) It("returns the error", func() { err := agent.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-vitals-service-error")) }) }) It("sends job monitoring alerts to health manager", func() { handler.KeepOnRunning() monitAlert := boshalert.MonitAlert{ ID: "fake-monit-alert", Service: "fake-service", Event: "fake-event", Action: "fake-action", Date: "Sun, 22 May 2011 20:07:41 +0500", Description: "fake-description", } jobSupervisor.JobFailureAlert = &monitAlert // Fail the first time handler.Send is called for an alert (ignore heartbeats) handler.SendCallback = func(input fakembus.SendInput) { if input.Topic == boshhandler.Alert { handler.SendErr = errors.New("stop") } } err := agent.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("stop")) expectedAlert := boshalert.Alert{ ID: "fake-monit-alert", Severity: boshalert.SeverityDefault, Title: "fake-service - fake-event - fake-action", Summary: "fake-description", CreatedAt: int64(1306076861), } Expect(handler.SendInputs()).To(ContainElement(fakembus.SendInput{ Target: boshhandler.HealthMonitor, Topic: boshhandler.Alert, Message: expectedAlert, })) }) It("sends ssh alerts to health manager", func() { handler.KeepOnRunning() syslogMsg := boshsyslog.Msg{Content: "disconnected by user"} syslogServer.StartFirstSyslogMsg = &syslogMsg uuidGenerator.GeneratedUUID = "fake-uuid" // Fail the first time handler.Send is called for an alert (ignore heartbeats) handler.SendCallback = func(input fakembus.SendInput) { if input.Topic == boshhandler.Alert { handler.SendErr = errors.New("stop") } } err := agent.Run() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("stop")) expectedAlert := boshalert.Alert{ ID: "fake-uuid", Severity: boshalert.SeverityWarning, Title: "SSH Logout", Summary: "disconnected by user", CreatedAt: timeService.Now().Unix(), } Expect(handler.SendInputs()).To(ContainElement(fakembus.SendInput{ Target: boshhandler.HealthMonitor, Topic: boshhandler.Alert, Message: expectedAlert, })) }) }) }) }