func (s *Simulator) buildNewApp() { app := appfixture.NewAppFixture() if s.randomizer.Float64() < s.FractionOfAppsThatAreCrashed { s.AppInstanceState[app.AppGuid] = models.InstanceStateCrashed } else { s.AppInstanceState[app.AppGuid] = models.InstanceStateRunning } winner := "" lowball := 1000000 for dea, apps := range s.DEAs { if len(apps)+1 > s.MaxDEACapacity { continue } if len(apps) < lowball { lowball = len(apps) winner = dea } } if winner == "" { winner = s.buildDEA() } app.DeaGuid = winner s.DEAs[winner] = append(s.DEAs[winner], &app) s.Apps = append(s.Apps, &app) }
}) for _, numApps := range numberOfApps { numApps := numApps iteration := 1 Context(fmt.Sprintf("With %d apps", numApps), func() { Measure("Read/Write/Delete Performance", func(b Benchmarker) { fmt.Printf("%d apps iteration %d\n", numApps, iteration) iteration += 1 heartbeat := models.Heartbeat{ DeaGuid: models.Guid(), InstanceHeartbeats: []models.InstanceHeartbeat{}, } n := 0 for i := 0; i < numApps; i++ { app := appfixture.NewAppFixture() for j := 0; j < numberOfInstancesPerApp; j++ { heartbeat.InstanceHeartbeats = append(heartbeat.InstanceHeartbeats, app.InstanceAtIndex(j).Heartbeat()) n += 1 } } b.Time("WRITE", func() { err := store.SyncHeartbeats(heartbeat) Ω(err).ShouldNot(HaveOccured()) }, StorePerformanceReport{ NumApps: numApps, Subject: "write", }) b.Time("READ", func() {
) var _ = Describe("Prioritizing and sending messages in batches", func() { //Note: the sender is configured to only send 8 messages at a time //This is done by cli_runner_test.go when it generates the config Context("when there are start and stop messages", func() { var highPriorityAppGuids []string var lowPriorityAppGuids []string BeforeEach(func() { var desiredStates = []models.DesiredAppState{} var heartbeats = []models.Heartbeat{} lowPriorityAppGuids = make([]string, 0) for i := 0; i < 8; i += 1 { appToStart := appfixture.NewAppFixture() desiredState := appToStart.DesiredState(2) desiredStates = append(desiredStates, desiredState) lowPriorityAppGuids = append(lowPriorityAppGuids, appToStart.AppGuid) heartbeats = append(heartbeats, appToStart.Heartbeat(1)) } highPriorityAppGuids = make([]string, 0) for i := 0; i < 9; i += 1 { appToStart := appfixture.NewAppFixture() desiredState := appToStart.DesiredState(1) desiredStates = append(desiredStates, desiredState) highPriorityAppGuids = append(highPriorityAppGuids, appToStart.AppGuid) } for i := 0; i < 40; i += 1 {
BeforeEach(func() { var err error conf, err = config.DefaultConfig() Expect(err).NotTo(HaveOccurred()) wpool, err := workpool.NewWorkPool(conf.StoreMaxConcurrentRequests) Expect(err).NotTo(HaveOccurred()) storeAdapter, err = etcdstoreadapter.New( &etcdstoreadapter.ETCDOptions{ClusterUrls: etcdRunner.NodeURLS()}, wpool, ) Expect(err).NotTo(HaveOccurred()) err = storeAdapter.Connect() Expect(err).NotTo(HaveOccurred()) app1 = appfixture.NewAppFixture() app2 = appfixture.NewAppFixture() app3 = appfixture.NewAppFixture() store = NewStore(conf, storeAdapter, fakelogger.NewFakeLogger()) }) AfterEach(func() { storeAdapter.Disconnect() }) Describe("Syncing desired state", func() { BeforeEach(func() { err := store.SyncDesiredState( app1.DesiredState(1), app2.DesiredState(1),
) Describe("POST /bulk_app_state", func() { var b appfixture.AppFixture BeforeEach(func() { apiServerAddr = fmt.Sprintf("http://%s:%d", cliRunner.config.APIServerAddress, cliRunner.config.APIServerPort) requestGenerator = rata.NewRequestGenerator(apiServerAddr, apiserver.Routes) httpClient = &http.Client{ Transport: &http.Transport{}, } username = cliRunner.config.APIServerUsername password = cliRunner.config.APIServerPassword a = appfixture.NewAppFixture() b = appfixture.NewAppFixture() validRequest = fmt.Sprintf(`[{"droplet":"%s","version":"%s"}, {"droplet":"%s","version":"%s"}]`, a.AppGuid, a.AppVersion, b.AppGuid, b.AppVersion) simulator.SetDesiredState(a.DesiredState(2), b.DesiredState(3)) simulator.SetCurrentHeartbeats(a.Heartbeat(1), b.Heartbeat(1)) }) AfterEach(func() { cliRunner.StopAPIServer() }) Context("when the store is fresh", func() { BeforeEach(func() { simulator.Tick(simulator.TicksToAttainFreshness) cliRunner.StartAPIServer(simulator.currentTimestamp)
expectedStopMessage = models.NewPendingStopMessage(clock.Now(), 0, conf.GracePeriod(), undesiredApp.AppGuid, undesiredApp.AppVersion, undesiredApp.InstanceAtIndex(0).InstanceGuid, models.PendingStopMessageReasonExtra) Ω(stopMessages()).Should(ContainElement(EqualPendingStopMessage(expectedStopMessage))) }) }) Context("When the store is not fresh and/or fails to fetch data", func() { BeforeEach(func() { storeAdapter.Reset() desired := app.DesiredState(1) //this setup would, ordinarily, trigger a start and a stop store.SyncDesiredState( desired, ) store.SyncHeartbeats( appfixture.NewAppFixture().Heartbeat(0), ) }) Context("when the desired state is not fresh", func() { BeforeEach(func() { store.BumpActualFreshness(time.Unix(10, 0)) }) It("should not send any start or stop messages", func() { err := analyzer.Analyze() Ω(err).Should(Equal(storepackage.DesiredIsNotFreshError)) Ω(startMessages()).Should(BeEmpty()) Ω(stopMessages()).Should(BeEmpty()) }) })
var _ = Describe("Fetching from CC and storing the result in the Store", func() { var ( fetcher *desiredstatefetcher.DesiredStateFetcher a1 appfixture.AppFixture a2 appfixture.AppFixture a3 appfixture.AppFixture store storepackage.Store resultChan chan desiredstatefetcher.DesiredStateFetcherResult conf *config.Config storeAdapter *fakestoreadapter.FakeStoreAdapter ) BeforeEach(func() { storeAdapter = fakestoreadapter.New() resultChan = make(chan desiredstatefetcher.DesiredStateFetcherResult, 1) a1 = appfixture.NewAppFixture() a2 = appfixture.NewAppFixture() a3 = appfixture.NewAppFixture() stateServer.SetDesiredState([]models.DesiredAppState{ a1.DesiredState(1), a2.DesiredState(1), a3.DesiredState(1), }) conf, _ = config.DefaultConfig() store = storepackage.NewStore(conf, storeAdapter, fakelogger.NewFakeLogger()) fetcher = desiredstatefetcher.New(conf, store, fakemetricsaccountant.New(), httpclient.NewHttpClient(conf.SkipSSLVerification, conf.FetcherNetworkTimeout()), &timeprovider.RealTimeProvider{}, fakelogger.NewFakeLogger()) fetcher.Fetch(resultChan)
} Context("when a response with desired state is received", func() { var ( a1 appfixture.AppFixture a2 appfixture.AppFixture stoppedApp appfixture.AppFixture pendingStagingApp appfixture.AppFixture failedToStageApp appfixture.AppFixture deletedApp appfixture.AppFixture pendingStagingDesiredState models.DesiredAppState ) BeforeEach(func() { deletedApp = appfixture.NewAppFixture() store.SyncDesiredState(deletedApp.DesiredState(1)) a1 = appfixture.NewAppFixture() a2 = appfixture.NewAppFixture() stoppedApp = appfixture.NewAppFixture() stoppedDesiredState := stoppedApp.DesiredState(1) stoppedDesiredState.State = models.AppStateStopped pendingStagingApp = appfixture.NewAppFixture() pendingStagingDesiredState = pendingStagingApp.DesiredState(1) pendingStagingDesiredState.PackageState = models.AppPackageStatePending failedToStageApp = appfixture.NewAppFixture() failedStagingDesiredState := failedToStageApp.DesiredState(1)
It("should drop the request on the floor", func() { messageBus.Subscriptions["app.state"][0].Callback(&yagnats.Message{ Payload: []byte("{}"), }) Ω(messageBus.PublishedMessages).Should(BeEmpty()) }) }) Context("when the request contains the droplet and version", func() { var app appfixture.AppFixture var expectedApp AppResponse var validRequestPayload string BeforeEach(func() { app = appfixture.NewAppFixture() instanceHeartbeats := []models.InstanceHeartbeat{ app.InstanceAtIndex(0).Heartbeat(), app.InstanceAtIndex(1).Heartbeat(), app.InstanceAtIndex(2).Heartbeat(), } crashCount := models.CrashCount{ AppGuid: app.AppGuid, AppVersion: app.AppVersion, InstanceIndex: 1, CrashCount: 2, } expectedApp = AppResponse{ AppGuid: app.AppGuid, AppVersion: app.AppVersion,
}) Describe("Fetching all actual state", func() { Context("when there is none saved", func() { It("should come back empty", func() { results, err := store.GetInstanceHeartbeats() Ω(err).ShouldNot(HaveOccurred()) Ω(results).Should(BeEmpty()) }) }) Context("when there is actual state saved", func() { var heartbeatOnDea, heartbeatOnOtherDea models.InstanceHeartbeat BeforeEach(func() { appOnBothDeas := appfixture.NewAppFixture() heartbeatOnDea = appOnBothDeas.InstanceAtIndex(0).Heartbeat() heartbeatOnDea.DeaGuid = dea.DeaGuid heartbeatOnOtherDea = appOnBothDeas.InstanceAtIndex(1).Heartbeat() heartbeatOnOtherDea.DeaGuid = otherDea.DeaGuid store.SyncHeartbeats(dea.HeartbeatWith( dea.GetApp(0).InstanceAtIndex(1).Heartbeat(), dea.GetApp(1).InstanceAtIndex(3).Heartbeat(), heartbeatOnDea, )) store.SyncHeartbeats(otherDea.HeartbeatWith( otherDea.GetApp(0).InstanceAtIndex(1).Heartbeat(),