Ejemplo n.º 1
0
func init() {
	Describe("concreteApplier", func() {
		var (
			jobApplier        *fakeja.FakeJobApplier
			packageApplier    *fakepa.FakePackageApplier
			logRotateDelegate *FakeLogRotateDelegate
			jobSupervisor     *fakejobsuper.FakeJobSupervisor
			applier           Applier
		)

		BeforeEach(func() {
			jobApplier = fakeja.NewFakeJobApplier()
			packageApplier = fakepa.NewFakePackageApplier()
			logRotateDelegate = &FakeLogRotateDelegate{}
			jobSupervisor = fakejobsuper.NewFakeJobSupervisor()
			applier = NewConcreteApplier(
				jobApplier,
				packageApplier,
				logRotateDelegate,
				jobSupervisor,
				boshdirs.NewDirectoriesProvider("/fake-base-dir"),
			)
		})

		It("removes all jobs", func() {
			err := applier.Apply(&fakeas.FakeApplySpec{})
			Expect(err).ToNot(HaveOccurred())

			Expect(jobSupervisor.RemovedAllJobs).To(BeTrue())
		})

		It("removes all previous jobs before starting to apply jobs", func() {
			// force remove all error
			jobSupervisor.RemovedAllJobsErr = errors.New("fake-remove-all-jobs-error")

			job := buildJob()
			applier.Apply(&fakeas.FakeApplySpec{JobResults: []models.Job{job}})

			// check that jobs were not applied before removing all other jobs
			Expect(jobApplier.AppliedJobs).To(Equal([]models.Job{}))
		})

		It("returns error if removing all jobs fails", func() {
			jobSupervisor.RemovedAllJobsErr = errors.New("fake-remove-all-jobs-error")

			err := applier.Apply(&fakeas.FakeApplySpec{})
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("fake-remove-all-jobs-error"))
		})

		It("apply applies jobs", func() {
			job := buildJob()

			err := applier.Apply(&fakeas.FakeApplySpec{JobResults: []models.Job{job}})
			Expect(err).ToNot(HaveOccurred())
			Expect(jobApplier.AppliedJobs).To(Equal([]models.Job{job}))
		})

		It("apply errs when applying jobs errs", func() {
			job := buildJob()

			jobApplier.ApplyError = errors.New("fake-apply-job-error")

			err := applier.Apply(&fakeas.FakeApplySpec{JobResults: []models.Job{job}})
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("fake-apply-job-error"))
		})

		It("apply applies packages", func() {
			pkg1 := buildPackage()
			pkg2 := buildPackage()

			err := applier.Apply(&fakeas.FakeApplySpec{PackageResults: []models.Package{pkg1, pkg2}})
			Expect(err).ToNot(HaveOccurred())
			Expect(packageApplier.AppliedPackages).To(Equal([]models.Package{pkg1, pkg2}))
		})

		It("apply errs when applying packages errs", func() {
			pkg := buildPackage()

			packageApplier.ApplyError = errors.New("fake-apply-package-error")

			err := applier.Apply(&fakeas.FakeApplySpec{PackageResults: []models.Package{pkg}})
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("fake-apply-package-error"))
		})

		It("apply configures jobs", func() {
			job1 := models.Job{Name: "fake-job-name-1", Version: "fake-version-name-1"}
			job2 := models.Job{Name: "fake-job-name-2", Version: "fake-version-name-2"}
			jobs := []models.Job{job1, job2}

			err := applier.Apply(&fakeas.FakeApplySpec{JobResults: jobs})
			Expect(err).ToNot(HaveOccurred())
			Expect(jobApplier.ConfiguredJobs).To(Equal([]models.Job{job2, job1}))
			Expect(jobApplier.ConfiguredJobIndices).To(Equal([]int{0, 1}))

			Expect(jobSupervisor.Reloaded).To(BeTrue())
		})

		It("apply errs if monitor fails reload", func() {
			jobs := []models.Job{}
			jobSupervisor.ReloadErr = errors.New("error reloading monit")

			err := applier.Apply(&fakeas.FakeApplySpec{JobResults: jobs})
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("error reloading monit"))
		})

		It("apply errs if a job fails configuring", func() {
			jobApplier.ConfigureError = errors.New("error configuring job")

			job := models.Job{Name: "fake-job-name-1", Version: "fake-version-name-1"}

			err := applier.Apply(&fakeas.FakeApplySpec{JobResults: []models.Job{job}})
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("error configuring job"))
		})

		It("apply sets up logrotation", func() {
			err := applier.Apply(&fakeas.FakeApplySpec{MaxLogFileSizeResult: "fake-size"})
			Expect(err).ToNot(HaveOccurred())
			assert.Equal(GinkgoT(), logRotateDelegate.SetupLogrotateArgs, SetupLogrotateArgs{
				GroupName: boshsettings.VCAP_USERNAME,
				BasePath:  "/fake-base-dir",
				Size:      "fake-size",
			})
		})

		It("apply errs if setup logrotate fails", func() {
			logRotateDelegate.SetupLogrotateErr = errors.New("fake-msg")

			err := applier.Apply(&fakeas.FakeApplySpec{})
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("Logrotate setup failed: fake-msg"))
		})
	})
}
Ejemplo n.º 2
0
func init() {
	Describe("Agent", func() {
		var (
			agent            Agent
			logger           boshlog.Logger
			handler          *fakembus.FakeHandler
			platform         *fakeplatform.FakePlatform
			actionDispatcher *FakeActionDispatcher
			alertBuilder     *fakealert.FakeAlertBuilder
			alertSender      AlertSender
			jobSupervisor    *fakejobsuper.FakeJobSupervisor
			specService      *fakeas.FakeV1Service
		)

		BeforeEach(func() {
			logger = boshlog.NewLogger(boshlog.LevelDebug)
			handler = &fakembus.FakeHandler{}
			platform = fakeplatform.NewFakePlatform()
			actionDispatcher = &FakeActionDispatcher{}
			alertBuilder = fakealert.NewFakeAlertBuilder()
			alertSender = NewAlertSender(handler, alertBuilder)
			jobSupervisor = fakejobsuper.NewFakeJobSupervisor()
			specService = fakeas.NewFakeV1Service()
			agent = New(logger, handler, platform, actionDispatcher, alertSender, jobSupervisor, specService, 5*time.Millisecond)
		})

		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 := boshmbus.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, alertSender, jobSupervisor, specService, 5*time.Hour)

					// Immediately exit after sending initial heartbeat
					handler.SendToHealthManagerErr = errors.New("stop")

					err := agent.Run()
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("stop"))

					Expect(handler.HMRequests()).To(Equal([]fakembus.HMRequest{
						fakembus.HMRequest{Topic: "heartbeat", Payload: expectedHb},
					}))
				})

				It("sends periodic heartbeats", func() {
					sentRequests := 0
					handler.SendToHealthManagerCallBack = func(_ fakembus.HMRequest) {
						sentRequests++
						if sentRequests == 3 {
							handler.SendToHealthManagerErr = errors.New("stop")
						}
					}

					err := agent.Run()
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("stop"))

					Expect(handler.HMRequests()).To(Equal([]fakembus.HMRequest{
						fakembus.HMRequest{Topic: "heartbeat", Payload: expectedHb},
						fakembus.HMRequest{Topic: "heartbeat", Payload: expectedHb},
						fakembus.HMRequest{Topic: "heartbeat", Payload: 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 failure alerts to health manager", func() {
				handler.KeepOnRunning()

				failureAlert := boshalert.MonitAlert{ID: "fake-monit-alert"}
				jobSupervisor.JobFailureAlert = &failureAlert

				builtAlert := boshalert.Alert{ID: "fake-built-alert"}
				alertBuilder.BuildAlert = builtAlert

				// Immediately exit from Run() after alert is sent
				handler.SendToHealthManagerCallBack = func(hmRequest fakembus.HMRequest) {
					if hmRequest.Topic == "alert" {
						handler.SendToHealthManagerErr = errors.New("stop")
					}
				}

				err := agent.Run()
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("stop"))

				Expect(alertBuilder.BuildInput).To(Equal(failureAlert))

				// Check for inclusion because heartbeats might have been received
				Expect(handler.HMRequests()).To(ContainElement(
					fakembus.HMRequest{Topic: "alert", Payload: builtAlert},
				))
			})
		})
	})
}
Ejemplo n.º 3
0
func init() {
	Describe("DrainAction", func() {
		var (
			notifier            *fakenotif.FakeNotifier
			specService         *fakeas.FakeV1Service
			drainScriptProvider *fakedrain.FakeDrainScriptProvider
			jobSupervisor       *fakejobsuper.FakeJobSupervisor
			action              DrainAction
		)

		BeforeEach(func() {
			notifier = fakenotif.NewFakeNotifier()
			specService = fakeas.NewFakeV1Service()
			drainScriptProvider = fakedrain.NewFakeDrainScriptProvider()
			jobSupervisor = fakejobsuper.NewFakeJobSupervisor()
			action = NewDrain(notifier, specService, drainScriptProvider, jobSupervisor)
		})

		BeforeEach(func() {
			drainScriptProvider.NewDrainScriptDrainScript.ExistsBool = true
		})

		It("is asynchronous", func() {
			Expect(action.IsAsynchronous()).To(BeTrue())
		})

		It("is not persistent", func() {
			Expect(action.IsPersistent()).To(BeFalse())
		})

		Context("when drain update is requested", func() {
			act := func() (int, error) { return action.Run(DrainTypeUpdate, boshas.V1ApplySpec{}) }

			Context("when current agent has a job spec template", func() {
				var currentSpec boshas.V1ApplySpec

				BeforeEach(func() {
					currentSpec = boshas.V1ApplySpec{}
					currentSpec.JobSpec.Template = "foo"
					specService.Spec = currentSpec
				})

				It("unmonitors services so that drain scripts can kill processes on their own", func() {
					value, err := act()
					Expect(err).ToNot(HaveOccurred())
					Expect(value).To(Equal(1))

					Expect(jobSupervisor.Unmonitored).To(BeTrue())
				})

				Context("when unmonitoring services succeeds", func() {
					It("does not notify of job shutdown", func() {
						value, err := act()
						Expect(err).ToNot(HaveOccurred())
						Expect(value).To(Equal(1))

						Expect(notifier.NotifiedShutdown).To(BeFalse())
					})

					Context("when new apply spec is provided", func() {
						newSpec := boshas.V1ApplySpec{
							PackageSpecs: map[string]boshas.PackageSpec{
								"foo": boshas.PackageSpec{
									Name: "foo",
									Sha1: "foo-sha1-new",
								},
							},
						}

						Context("when drain script exists", func() {
							It("runs drain script with job_shutdown param", func() {
								value, err := action.Run(DrainTypeUpdate, newSpec)
								Expect(err).ToNot(HaveOccurred())
								Expect(value).To(Equal(1))

								Expect(drainScriptProvider.NewDrainScriptTemplateName).To(Equal("foo"))
								Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeTrue())

								params := drainScriptProvider.NewDrainScriptDrainScript.RunParams
								Expect(params).To(Equal(boshdrain.NewUpdateDrainParams(currentSpec, newSpec)))
							})

							Context("when drain script runs and errs", func() {
								It("returns error", func() {
									drainScriptProvider.NewDrainScriptDrainScript.RunError = errors.New("fake-drain-run-error")

									value, err := act()
									Expect(err).To(HaveOccurred())
									Expect(err.Error()).To(ContainSubstring("fake-drain-run-error"))
									Expect(value).To(Equal(0))
								})
							})
						})

						Context("when drain script does not exist", func() {
							It("returns 0", func() {
								drainScriptProvider.NewDrainScriptDrainScript.ExistsBool = false

								value, err := act()
								Expect(err).ToNot(HaveOccurred())
								Expect(value).To(Equal(0))

								Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeFalse())
							})
						})
					})

					Context("when apply spec is not provided", func() {
						It("returns error", func() {
							value, err := action.Run(DrainTypeUpdate)
							Expect(err).To(HaveOccurred())
							Expect(err.Error()).To(ContainSubstring("Drain update requires new spec"))
							Expect(value).To(Equal(0))
						})
					})
				})

				Context("when unmonitoring services fails", func() {
					It("returns error", func() {
						jobSupervisor.UnmonitorErr = errors.New("fake-unmonitor-error")

						value, err := act()
						Expect(err).To(HaveOccurred())
						Expect(err.Error()).To(ContainSubstring("fake-unmonitor-error"))
						Expect(value).To(Equal(0))
					})
				})
			})

			Context("when current agent spec does not have a job spec template", func() {
				It("returns 0 and does not run drain script", func() {
					specService.Spec = boshas.V1ApplySpec{}

					value, err := act()
					Expect(err).ToNot(HaveOccurred())
					Expect(value).To(Equal(0))

					Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeFalse())
				})
			})
		})

		Context("when drain shutdown is requested", func() {
			act := func() (int, error) { return action.Run(DrainTypeShutdown) }

			Context("when current agent has a job spec template", func() {
				var currentSpec boshas.V1ApplySpec

				BeforeEach(func() {
					currentSpec = boshas.V1ApplySpec{}
					currentSpec.JobSpec.Template = "foo"
					specService.Spec = currentSpec
				})

				It("unmonitors services so that drain scripts can kill processes on their own", func() {
					value, err := act()
					Expect(err).ToNot(HaveOccurred())
					Expect(value).To(Equal(1))

					Expect(jobSupervisor.Unmonitored).To(BeTrue())
				})

				Context("when unmonitoring services succeeds", func() {
					It("notifies that job is about to shutdown", func() {
						value, err := act()
						Expect(err).ToNot(HaveOccurred())
						Expect(value).To(Equal(1))

						Expect(notifier.NotifiedShutdown).To(BeTrue())
					})

					Context("when job shutdown notification succeeds", func() {
						Context("when drain script exists", func() {
							It("runs drain script with job_shutdown param passing no apply spec", func() {
								value, err := action.Run(DrainTypeShutdown)
								Expect(err).ToNot(HaveOccurred())
								Expect(value).To(Equal(1))

								Expect(drainScriptProvider.NewDrainScriptTemplateName).To(Equal("foo"))
								Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeTrue())

								params := drainScriptProvider.NewDrainScriptDrainScript.RunParams
								Expect(params).To(Equal(boshdrain.NewShutdownDrainParams(currentSpec, nil)))
							})

							It("runs drain script with job_shutdown param passing in first apply spec", func() {
								newSpec := boshas.V1ApplySpec{}
								newSpec.JobSpec.Template = "fake-updated-template"

								value, err := action.Run(DrainTypeShutdown, newSpec)
								Expect(err).ToNot(HaveOccurred())
								Expect(value).To(Equal(1))

								Expect(drainScriptProvider.NewDrainScriptTemplateName).To(Equal("foo"))
								Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeTrue())

								params := drainScriptProvider.NewDrainScriptDrainScript.RunParams
								Expect(params).To(Equal(boshdrain.NewShutdownDrainParams(currentSpec, &newSpec)))
							})

							Context("when drain script runs and errs", func() {
								It("returns error", func() {
									drainScriptProvider.NewDrainScriptDrainScript.RunError = errors.New("fake-drain-run-error")

									value, err := act()
									Expect(err).To(HaveOccurred())
									Expect(err.Error()).To(ContainSubstring("fake-drain-run-error"))
									Expect(value).To(Equal(0))
								})
							})
						})

						Context("when drain script does not exist", func() {
							It("returns 0", func() {
								drainScriptProvider.NewDrainScriptDrainScript.ExistsBool = false

								value, err := act()
								Expect(err).ToNot(HaveOccurred())
								Expect(value).To(Equal(0))

								Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeFalse())
							})
						})
					})

					Context("when job shutdown notification fails", func() {
						It("returns error if job shutdown notifications errs", func() {
							notifier.NotifyShutdownErr = errors.New("fake-shutdown-error")

							value, err := act()
							Expect(err).To(HaveOccurred())
							Expect(err.Error()).To(ContainSubstring("fake-shutdown-error"))
							Expect(value).To(Equal(0))
						})
					})
				})

				Context("when unmonitoring services fails", func() {
					It("returns error", func() {
						jobSupervisor.UnmonitorErr = errors.New("fake-unmonitor-error")

						value, err := act()
						Expect(err).To(HaveOccurred())
						Expect(err.Error()).To(ContainSubstring("fake-unmonitor-error"))
						Expect(value).To(Equal(0))
					})
				})
			})

			Context("when current agent spec does not have a job spec template", func() {
				It("returns 0 and does not run drain script", func() {
					specService.Spec = boshas.V1ApplySpec{}

					value, err := act()
					Expect(err).ToNot(HaveOccurred())
					Expect(value).To(Equal(0))

					Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeFalse())
				})
			})
		})

		Context("when drain status is requested", func() {
			act := func() (int, error) { return action.Run(DrainTypeStatus) }

			Context("when current agent has a job spec template", func() {
				var currentSpec boshas.V1ApplySpec

				BeforeEach(func() {
					currentSpec = boshas.V1ApplySpec{}
					currentSpec.JobSpec.Template = "foo"
					specService.Spec = currentSpec
				})

				It("unmonitors services so that drain scripts can kill processes on their own", func() {
					value, err := act()
					Expect(err).ToNot(HaveOccurred())
					Expect(value).To(Equal(1))

					Expect(jobSupervisor.Unmonitored).To(BeTrue())
				})

				It("does not notify of job shutdown", func() {
					value, err := act()
					Expect(err).ToNot(HaveOccurred())
					Expect(value).To(Equal(1))

					Expect(notifier.NotifiedShutdown).To(BeFalse())
				})

				Context("when unmonitoring services succeeds", func() {
					Context("when drain script exists", func() {
						It("runs drain script with job_check_status param passing no apply spec", func() {
							value, err := action.Run(DrainTypeStatus)
							Expect(err).ToNot(HaveOccurred())
							Expect(value).To(Equal(1))

							Expect(drainScriptProvider.NewDrainScriptTemplateName).To(Equal("foo"))
							Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeTrue())

							params := drainScriptProvider.NewDrainScriptDrainScript.RunParams
							Expect(params).To(Equal(boshdrain.NewStatusDrainParams(currentSpec, nil)))
						})

						It("runs drain script with job_check_status param passing in first apply spec", func() {
							newSpec := boshas.V1ApplySpec{}
							newSpec.JobSpec.Template = "fake-updated-template"

							value, err := action.Run(DrainTypeStatus, newSpec)
							Expect(err).ToNot(HaveOccurred())
							Expect(value).To(Equal(1))

							Expect(drainScriptProvider.NewDrainScriptTemplateName).To(Equal("foo"))
							Expect(drainScriptProvider.NewDrainScriptDrainScript.DidRun).To(BeTrue())

							params := drainScriptProvider.NewDrainScriptDrainScript.RunParams
							Expect(params).To(Equal(boshdrain.NewStatusDrainParams(currentSpec, &newSpec)))
						})

						Context("when drain script runs and errs", func() {
							It("returns error if drain script errs", func() {
								drainScriptProvider.NewDrainScriptDrainScript.RunError = errors.New("fake-drain-run-error")

								value, err := act()
								Expect(err).To(HaveOccurred())
								Expect(err.Error()).To(ContainSubstring("fake-drain-run-error"))
								Expect(value).To(Equal(0))
							})
						})
					})

					Context("when drain script does not exist", func() {
						It("returns error because drain status must be called after starting draining", func() {
							drainScriptProvider.NewDrainScriptDrainScript.ExistsBool = false

							value, err := act()
							Expect(err).To(HaveOccurred())
							Expect(err.Error()).To(ContainSubstring("Check Status on Drain action requires a valid drain script"))
							Expect(value).To(Equal(0))
						})
					})
				})

				Context("when unmonitoring services fails", func() {
					It("returns error if unmonitoring services errs", func() {
						jobSupervisor.UnmonitorErr = errors.New("fake-unmonitor-error")

						value, err := act()
						Expect(err).To(HaveOccurred())
						Expect(err.Error()).To(ContainSubstring("fake-unmonitor-error"))
						Expect(value).To(Equal(0))
					})
				})
			})

			Context("when current agent spec does not have a job spec template", func() {
				It("returns error because drain status should only be called after starting draining", func() {
					specService.Spec = boshas.V1ApplySpec{}

					value, err := action.Run(DrainTypeStatus)
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("Check Status on Drain action requires job spec"))
					Expect(value).To(Equal(0))
				})
			})
		})
	})
}
Ejemplo n.º 4
0
func init() {
	Describe("Agent", func() {
		var (
			agent            Agent
			logger           boshlog.Logger
			handler          *fakembus.FakeHandler
			platform         *fakeplatform.FakePlatform
			actionDispatcher *FakeActionDispatcher
			alertBuilder     *fakealert.FakeAlertBuilder
			jobSupervisor    *fakejobsuper.FakeJobSupervisor
			specService      *fakeas.FakeV1Service
		)

		BeforeEach(func() {
			logger = boshlog.NewLogger(boshlog.LEVEL_NONE)
			handler = &fakembus.FakeHandler{}
			platform = fakeplatform.NewFakePlatform()
			actionDispatcher = &FakeActionDispatcher{}
			alertBuilder = fakealert.NewFakeAlertBuilder()
			jobSupervisor = fakejobsuper.NewFakeJobSupervisor()
			specService = fakeas.NewFakeV1Service()
			agent = New(logger, handler, platform, actionDispatcher, alertBuilder, jobSupervisor, specService, 5*time.Millisecond)
		})

		Describe("Run", func() {
			It("sets the dispatcher as message handler", func() {
				actionDispatcher.DispatchResp = boshhandler.NewValueResponse("pong")

				err := agent.Run()
				Expect(err).ToNot(HaveOccurred())
				Expect(handler.ReceivedRun).To(BeTrue())

				req := boshhandler.NewRequest("fake-reply", "fake-action", []byte("fake-payload"))
				resp := handler.Func(req)

				Expect(req).To(Equal(actionDispatcher.DispatchReq))
				Expect(actionDispatcher.DispatchResp).To(Equal(resp))
			})

			It("resumes persistent actions *before* dispatching new requests", func() {
				resumedBefore := false
				handler.RunFunc = func() {
					resumedBefore = actionDispatcher.ResumedPreviouslyDispatchedTasks
				}

				err := agent.Run()
				Expect(err).ToNot(HaveOccurred())
				Expect(resumedBefore).To(BeTrue())
			})

			Context("when heartbeats can be sent", func() {
				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 := boshmbus.Heartbeat{
					Job:      &expectedJobName,
					Index:    &expectedJobIndex,
					JobState: "fake-state",
					Vitals:   boshvitals.Vitals{Load: []string{"a", "b", "c"}},
				}

				It("sends initial heartbeat", func() {
					err := agent.Run()
					Expect(err).ToNot(HaveOccurred())

					Expect(handler.InitialHeartbeatSent).To(BeTrue())
					Expect(handler.TickHeartbeatsSent).To(BeFalse())

					Expect(handler.SendToHealthManagerTopic).To(Equal("heartbeat"))
					Expect(handler.SendToHealthManagerPayload.(boshmbus.Heartbeat)).To(Equal(expectedHb))
				})

				It("sends periodic heartbeats", func() {
					err := agent.Run()
					Expect(err).ToNot(HaveOccurred())

					Expect(handler.TickHeartbeatsSent).To(BeFalse())
					time.Sleep(5 * time.Millisecond)
					Expect(handler.TickHeartbeatsSent).To(BeTrue())

					Expect(handler.SendToHealthManagerTopic).To(Equal("heartbeat"))
					Expect(handler.SendToHealthManagerPayload.(boshmbus.Heartbeat)).To(Equal(expectedHb))
				})
			})

			Context("when the agent fails to get job spec for a heartbeat", func() {
				BeforeEach(func() {
					block := make(chan error)
					handler.RunFunc = func() { <-block }
					specService.GetErr = errors.New("fake-spec-service-error")
				})

				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() {
					block := make(chan error)
					handler.RunFunc = func() { <-block }
					platform.FakeVitalsService.GetErr = errors.New("fake-vitals-service-error")
				})

				It("returns the error", func() {
					err := agent.Run()
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("fake-vitals-service-error"))
				})
			})

			It("sets the callback for job failures monitoring", func() {
				builtAlert := boshalert.Alert{Id: "some built alert id"}
				alertBuilder.BuildAlert = builtAlert

				err := agent.Run()
				Expect(err).ToNot(HaveOccurred())
				Expect(handler.SendToHealthManagerTopic).ToNot(Equal("alert"))

				failureAlert := boshalert.MonitAlert{Id: "some random id"}
				jobSupervisor.OnJobFailure(failureAlert)

				Expect(failureAlert).To(Equal(alertBuilder.BuildInput))
				Expect(handler.SendToHealthManagerTopic).To(Equal("alert"))
				Expect(builtAlert).To(Equal(handler.SendToHealthManagerPayload))
			})
		})
	})
}
Ejemplo n.º 5
0
	fakeas "bosh/agent/applier/applyspec/fakes"
	boshassert "bosh/assert"
	fakejobsuper "bosh/jobsupervisor/fakes"
	boshntp "bosh/platform/ntp"
	fakentp "bosh/platform/ntp/fakes"
	boshvitals "bosh/platform/vitals"
	fakevitals "bosh/platform/vitals/fakes"
	boshsettings "bosh/settings"
	fakesettings "bosh/settings/fakes"
)

var _ = Describe("GetState", func() {
	var (
		settings      *fakesettings.FakeSettingsService
		specService   *fakeas.FakeV1Service
		jobSupervisor *fakejobsuper.FakeJobSupervisor
		vitalsService *fakevitals.FakeService
		action        GetStateAction
	)

	BeforeEach(func() {
		settings = &fakesettings.FakeSettingsService{}
		jobSupervisor = fakejobsuper.NewFakeJobSupervisor()
		specService = fakeas.NewFakeV1Service()
		vitalsService = fakevitals.NewFakeService()
		action = NewGetState(settings, specService, jobSupervisor, vitalsService, &fakentp.FakeService{
			GetOffsetNTPOffset: boshntp.NTPInfo{
				Offset:    "0.34958",
				Timestamp: "12 Oct 17:37:58",
			},
		})