func (db *SQLDB) DesireLRP(logger lager.Logger, desiredLRP *models.DesiredLRP) error { logger = logger.WithData(lager.Data{"process_guid": desiredLRP.ProcessGuid}) logger.Info("starting") defer logger.Info("complete") return db.transact(logger, func(logger lager.Logger, tx *sql.Tx) error { routesData, err := json.Marshal(desiredLRP.Routes) runInfo := desiredLRP.DesiredLRPRunInfo(db.clock.Now()) runInfoData, err := db.serializeModel(logger, &runInfo) if err != nil { logger.Error("failed-to-serialize-model", err) return err } volumePlacement := &models.VolumePlacement{} volumePlacement.DriverNames = []string{} for _, mount := range desiredLRP.VolumeMounts { volumePlacement.DriverNames = append(volumePlacement.DriverNames, mount.Driver) } volumePlacementData, err := db.serializeModel(logger, volumePlacement) if err != nil { logger.Error("failed-to-serialize-model", err) return err } guid, err := db.guidProvider.NextGUID() if err != nil { logger.Error("failed-to-generate-guid", err) return models.ErrGUIDGeneration } desiredLRP.ModificationTag = &models.ModificationTag{Epoch: guid, Index: 0} _, err = db.insert(logger, tx, desiredLRPsTable, SQLAttributes{ "process_guid": desiredLRP.ProcessGuid, "domain": desiredLRP.Domain, "log_guid": desiredLRP.LogGuid, "annotation": desiredLRP.Annotation, "instances": desiredLRP.Instances, "memory_mb": desiredLRP.MemoryMb, "disk_mb": desiredLRP.DiskMb, "rootfs": desiredLRP.RootFs, "volume_placement": volumePlacementData, "modification_tag_epoch": desiredLRP.ModificationTag.Epoch, "modification_tag_index": desiredLRP.ModificationTag.Index, "routes": routesData, "run_info": runInfoData, }, ) if err != nil { logger.Error("failed-inserting-desired", err) return db.convertSQLError(err) } return nil }) }
func (db *ETCDDB) DesiredLRPs(logger lager.Logger, filter models.DesiredLRPFilter) (*models.DesiredLRPs, *models.Error) { root, bbsErr := db.fetchRecursiveRaw(logger, DesiredLRPSchemaRoot) if bbsErr.Equal(models.ErrResourceNotFound) { return &models.DesiredLRPs{}, nil } if bbsErr != nil { return nil, bbsErr } if root.Nodes.Len() == 0 { return &models.DesiredLRPs{}, nil } desiredLRPs := models.DesiredLRPs{} lrpsLock := sync.Mutex{} var workErr atomic.Value works := []func(){} for _, node := range root.Nodes { node := node works = append(works, func() { var lrp models.DesiredLRP deserializeErr := models.FromJSON([]byte(node.Value), &lrp) if deserializeErr != nil { logger.Error("failed-parsing-desired-lrp", deserializeErr) workErr.Store(fmt.Errorf("cannot parse lrp JSON for key %s: %s", node.Key, deserializeErr.Error())) return } if filter.Domain == "" || lrp.GetDomain() == filter.Domain { lrpsLock.Lock() desiredLRPs.DesiredLrps = append(desiredLRPs.DesiredLrps, &lrp) lrpsLock.Unlock() } }) } throttler, err := workpool.NewThrottler(maxDesiredLRPGetterWorkPoolSize, works) if err != nil { logger.Error("failed-constructing-throttler", err, lager.Data{"max-workers": maxDesiredLRPGetterWorkPoolSize, "num-works": len(works)}) return &models.DesiredLRPs{}, models.ErrUnknownError } logger.Debug("performing-deserialization-work") throttler.Work() if err, ok := workErr.Load().(error); ok { logger.Error("failed-performing-deserialization-work", err) return &models.DesiredLRPs{}, models.ErrUnknownError } logger.Debug("succeeded-performing-deserialization-work", lager.Data{"num-desired-lrps": len(desiredLRPs.GetDesiredLrps())}) return &desiredLRPs, nil }
func prettyPrint(encrypted []byte, key string, label string) { var decrypted, err = decrypt(encrypted, key, label) if err != nil { return } var model1 models.DesiredLRPRunInfo err = model1.Unmarshal(decrypted) if err != nil { // NOP } else { pretty.Println(model1) return } var model2 models.DesiredLRPSchedulingInfo err = model2.Unmarshal(decrypted) if err != nil { // NOP } else { pretty.Println(model2) return } var model3 models.ActualLRP err = model3.Unmarshal(decrypted) if err != nil { // NOP } else { pretty.Println(model3) return } var model4 models.Task err = model4.Unmarshal(decrypted) if err != nil { // NOP } else { pretty.Println(model4) return } var model5 models.DesiredLRP err = model5.Unmarshal(decrypted) if err != nil { log.Println("Unknown data type: ", string(decrypted)) } else { pretty.Println(model5) return } }
// DesireLRP creates a DesiredLRPSchedulingInfo and a DesiredLRPRunInfo. In order // to ensure that the complete model is available and there are no races in // Desired Watches, DesiredLRPRunInfo is created before DesiredLRPSchedulingInfo. func (db *ETCDDB) DesireLRP(logger lager.Logger, desiredLRP *models.DesiredLRP) error { logger = logger.Session("create-desired-lrp", lager.Data{"process-guid": desiredLRP.ProcessGuid}) logger.Info("starting") defer logger.Info("complete") schedulingInfo, runInfo := desiredLRP.Explode() err := db.createDesiredLRPRunInfo(logger, &runInfo) if err != nil { return err } err = db.createDesiredLRPSchedulingInfo(logger, &schedulingInfo) if err != nil { return err } db.startInstanceRange(logger, 0, schedulingInfo.Instances, &schedulingInfo) return nil }
func (db *ETCDDB) UpdateDesiredLRP(logger lager.Logger, processGuid string, update *models.DesiredLRPUpdate) (*models.DesiredLRP, error) { logger.Info("starting") defer logger.Info("complete") var schedulingInfo *models.DesiredLRPSchedulingInfo var err error var beforeDesiredLRP *models.DesiredLRP for i := 0; i < 2; i++ { var index uint64 beforeDesiredLRP, index, err = db.rawDesiredLRPByProcessGuid(logger, processGuid) if err != nil { logger.Error("failed-to-fetch-desired-lrp", err) break } schedulingInfoValue := beforeDesiredLRP.DesiredLRPSchedulingInfo() schedulingInfo = &schedulingInfoValue schedulingInfo.ApplyUpdate(update) err = db.updateDesiredLRPSchedulingInfo(logger, schedulingInfo, index) if err != nil { logger.Error("update-scheduling-info-failed", err) modelErr := models.ConvertError(err) if modelErr != models.ErrResourceConflict { break } // Retry on CAS fail continue } break } if err != nil { return nil, err } return beforeDesiredLRP, nil }
func (h *DesiredLRPHandler) DesiredLRPByProcessGuid_r1(w http.ResponseWriter, req *http.Request) { var err error logger := h.logger.Session("desired-lrp-by-process-guid", lager.Data{"revision": 0}) request := &models.DesiredLRPByProcessGuidRequest{} response := &models.DesiredLRPResponse{} err = parseRequest(logger, req, request) if err == nil { var lrp *models.DesiredLRP lrp, err = h.desiredLRPDB.DesiredLRPByProcessGuid(logger, request.ProcessGuid) if err == nil { transformedLRP := lrp.VersionDownTo(format.V1) response.DesiredLrp = transformedLRP } } response.Error = models.ConvertError(err) writeResponse(w, response) exitIfUnrecoverable(logger, h.exitChan, response.Error) }
// DesireLRP creates a DesiredLRPSchedulingInfo and a DesiredLRPRunInfo. In order // to ensure that the complete model is available and there are no races in // Desired Watches, DesiredLRPRunInfo is created before DesiredLRPSchedulingInfo. func (db *ETCDDB) DesireLRP(logger lager.Logger, desiredLRP *models.DesiredLRP) error { logger = logger.WithData(lager.Data{"process_guid": desiredLRP.ProcessGuid}) logger.Info("starting") defer logger.Info("complete") schedulingInfo, runInfo := desiredLRP.CreateComponents(db.clock.Now()) err := db.createDesiredLRPRunInfo(logger, &runInfo) if err != nil { return err } schedulingErr := db.createDesiredLRPSchedulingInfo(logger, &schedulingInfo) if schedulingErr != nil { logger.Info("deleting-orphaned-run-info") _, err = db.client.Delete(DesiredLRPRunInfoSchemaPath(desiredLRP.ProcessGuid), true) if err != nil { logger.Error("failed-deleting-orphaned-run-info", err) } return schedulingErr } return nil }
func (m *SplitDesiredLRP) WriteRunInfo(logger lager.Logger, desiredLRP models.DesiredLRP) { environmentVariables := make([]models.EnvironmentVariable, len(desiredLRP.EnvironmentVariables)) for i := range desiredLRP.EnvironmentVariables { environmentVariables[i] = *desiredLRP.EnvironmentVariables[i] } egressRules := make([]models.SecurityGroupRule, len(desiredLRP.EgressRules)) for i := range desiredLRP.EgressRules { egressRules[i] = *desiredLRP.EgressRules[i] } runInfo := models.DesiredLRPRunInfo{ DesiredLRPKey: desiredLRP.DesiredLRPKey(), EnvironmentVariables: environmentVariables, Setup: desiredLRP.Setup, Action: desiredLRP.Action, Monitor: desiredLRP.Monitor, StartTimeoutMs: desiredLRP.StartTimeoutMs, Privileged: desiredLRP.Privileged, CpuWeight: desiredLRP.CpuWeight, Ports: desiredLRP.Ports, EgressRules: egressRules, LogSource: desiredLRP.LogSource, MetricsGuid: desiredLRP.MetricsGuid, } runInfoPayload, marshalErr := m.serializer.Marshal(logger, format.ENCRYPTED_PROTO, &runInfo) if marshalErr != nil { logger.Error("failed-marshaling-run-info", marshalErr, lager.Data{"process_guid": runInfo.ProcessGuid}) } _, setErr := m.storeClient.Set(etcd.DesiredLRPRunInfoSchemaPath(runInfo.ProcessGuid), runInfoPayload, etcd.NO_TTL) if setErr != nil { logger.Error("failed-set-of-run-info", marshalErr, lager.Data{"process_guid": runInfo.ProcessGuid}) } }
func (m *SplitDesiredLRP) WriteSchedulingInfo(logger lager.Logger, desiredLRP models.DesiredLRP) { schedulingInfo := models.DesiredLRPSchedulingInfo{ DesiredLRPKey: desiredLRP.DesiredLRPKey(), Annotation: desiredLRP.Annotation, Instances: desiredLRP.Instances, DesiredLRPResource: desiredLRP.DesiredLRPResource(), } if desiredLRP.Routes != nil { schedulingInfo.Routes = *desiredLRP.Routes } if desiredLRP.ModificationTag != nil { schedulingInfo.ModificationTag = *desiredLRP.ModificationTag } schedulingInfoPayload, marshalErr := m.serializer.Marshal(logger, format.ENCRYPTED_PROTO, &schedulingInfo) if marshalErr != nil { logger.Error("failed-marshaling-scheduling-info", marshalErr, lager.Data{"process_guid": schedulingInfo.ProcessGuid}) } _, setErr := m.storeClient.Set(etcd.DesiredLRPSchedulingInfoSchemaPath(desiredLRP.ProcessGuid), schedulingInfoPayload, etcd.NO_TTL) if setErr != nil { logger.Error("failed-set-of-scheduling-info", marshalErr, lager.Data{"process_guid": schedulingInfo.ProcessGuid}) } }
"encoding/json" . "github.com/cloudfoundry-incubator/bbs/db/etcd" "github.com/cloudfoundry-incubator/bbs/models" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" ) var _ = Describe("Watchers", func() { Describe("WatchForDesiredLRPChanges", func() { var ( creates chan *models.DesiredLRP changes chan *models.DesiredLRPChange deletes chan *models.DesiredLRP stop chan<- bool errors <-chan error lrp *models.DesiredLRP ) BeforeEach(func() { routePayload := json.RawMessage(`{"port":8080,"hosts":["route-1","route-2"]}`) lrp = &models.DesiredLRP{ ProcessGuid: "some-process-guid", Domain: "tests", RootFs: "some:rootfs", Action: models.WrapAction(&models.DownloadAction{ From: "http://example.com", To: "/tmp/internet", User: "******", }),
"golang.org/x/crypto/ssh" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("PermissionsBuilder", func() { Describe("Build", func() { var ( logger *lagertest.TestLogger expectedRoute routes.SSHRoute desiredLRP *models.DesiredLRP actualLRPGroup *models.ActualLRPGroup bbsClient *fake_bbs.FakeClient credentials []byte metadata *fake_ssh.FakeConnMetadata permissionsBuilder authenticators.PermissionsBuilder permissions *ssh.Permissions buildErr error processGuid string index int ) BeforeEach(func() { logger = lagertest.NewTestLogger("test") expectedRoute = routes.SSHRoute{ ContainerPort: 1111, PrivateKey: "pem-encoded-key", HostFingerprint: "host-fingerprint",
Context("on startup", func() { It("processes events after the first sync event", func() { Consistently(bbsClient.SubscribeToEventsCallCount).Should(Equal(0)) syncEvents.Sync <- struct{}{} Eventually(bbsClient.SubscribeToEventsCallCount).Should(BeNumerically(">", 0)) }) }) Describe("Desired LRP changes", func() { JustBeforeEach(func() { syncEvents.Sync <- struct{}{} Eventually(emitter.EmitCallCount).ShouldNot(Equal(0)) }) Context("when a create event occurs", func() { var desiredLRP *models.DesiredLRP BeforeEach(func() { routes := cfroutes.CFRoutes{expectedCFRoute}.RoutingInfo() desiredLRP = &models.DesiredLRP{ Action: models.WrapAction(&models.RunAction{ User: "******", Path: "ls", }), Domain: "tests", ProcessGuid: expectedProcessGuid, Ports: []uint32{expectedContainerPort}, Routes: &routes, LogGuid: logGuid, } })
func (t *ETCDHelper) SetRawDesiredLRP(lrp *models.DesiredLRP) { schedulingInfo, runInfo := lrp.CreateComponents(t.clock.Now()) t.SetRawDesiredLRPSchedulingInfo(&schedulingInfo) t.SetRawDesiredLRPRunInfo(&runInfo) }
"encoding/json" "fmt" "time" "github.com/cloudfoundry-incubator/bbs/format" "github.com/cloudfoundry-incubator/bbs/models" "github.com/cloudfoundry-incubator/bbs/models/test/model_helpers" "github.com/gogo/protobuf/proto" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" ) var _ = Describe("DesiredLRP", func() { var desiredLRP models.DesiredLRP jsonDesiredLRP := `{ "setup": { "serial": { "actions": [ { "download": { "from": "http://file-server.service.cf.internal:8080/v1/static/buildpack_app_lifecycle/buildpack_app_lifecycle.tgz", "to": "/tmp/lifecycle", "cache_key": "buildpack-cflinuxfs2-lifecycle", "user": "******", "checksum_algorithm": "md5", "checksum_value": "some random value" } },
etcdRunner.Stop() }) AfterEach(func() { etcdRunner.Start() }) It("errors", func() { _, err := etcdDB.DesiredLRPSchedulingInfos(logger, filter) Expect(err).To(HaveOccurred()) }) }) }) Describe("DesireLRP", func() { var lrp *models.DesiredLRP BeforeEach(func() { lrp = model_helpers.NewValidDesiredLRP("some-process-guid") lrp.Instances = 5 }) Context("when the desired LRP does not yet exist", func() { It("persists the scheduling info and run info", func() { err := etcdDB.DesireLRP(logger, lrp) Expect(err).NotTo(HaveOccurred()) persisted, err := etcdDB.DesiredLRPByProcessGuid(logger, "some-process-guid") Expect(err).NotTo(HaveOccurred()) Expect(persisted.DesiredLRPKey()).To(Equal(lrp.DesiredLRPKey()))
It("has the correct number of responses", func() { Expect(actualDesiredLRPs).To(HaveLen(2)) }) It("returns only the desired lrps in the requested domain", func() { for _, lrp := range desiredLRPs[domain] { expectedDesiredLRPs = append(expectedDesiredLRPs, lrp) } Expect(actualDesiredLRPs).To(ConsistOf(expectedDesiredLRPs)) }) }) }) Describe("GET /v1/desired_lrps/:process_guid", func() { var ( desiredLRP *models.DesiredLRP expectedDesiredLRP *models.DesiredLRP ) JustBeforeEach(func() { expectedDesiredLRP = desiredLRPs["domain-1"][0] desiredLRP, getErr = client.DesiredLRPByProcessGuid(expectedDesiredLRP.GetProcessGuid()) }) It("responds without error", func() { Expect(getErr).NotTo(HaveOccurred()) }) It("returns all desired lrps from the bbs", func() { Expect(desiredLRP).To(Equal(expectedDesiredLRP)) }) })
EgressRules: []*models.SecurityGroupRule{{ Protocol: models.TCPProtocol, Destinations: []string{"1.1.1.1/32", "2.2.2.2/32"}, PortRange: &models.PortRange{Start: 10, End: 16000}, }}, ModificationTag: &modTag, } err := desiredLRP.Validate() Expect(err).NotTo(HaveOccurred()) return desiredLRP } Describe("Up", func() { var ( existingDesiredLRP *models.DesiredLRP migrationErr error ) BeforeEach(func() { existingDesiredLRP = newValidDesiredLRP("process-guid") payload, err := serializer.Marshal(logger, format.ENCRYPTED_PROTO, existingDesiredLRP) Expect(err).NotTo(HaveOccurred()) _, err = storeClient.Set(deprecations.DesiredLRPSchemaPath(existingDesiredLRP), payload, 0) Expect(err).NotTo(HaveOccurred()) }) JustBeforeEach(func() { migration.SetStoreClient(storeClient) migration.SetCryptor(cryptor) migrationErr = migration.Up(logger) })
It("returns an error", func() { response := models.EvacuationResponse{} err := response.Unmarshal(responseRecorder.Body.Bytes()) Expect(err).NotTo(HaveOccurred()) Expect(response.KeepContainer).To(BeFalse()) Expect(response.Error).To(Equal(models.ErrBadRequest)) }) }) }) Describe("EvacuateRunningActualLRP", func() { var ( request *http.Request requestBody *models.EvacuateRunningActualLRPRequest actualLRPGroup *models.ActualLRPGroup desiredLRP *models.DesiredLRP actual *models.ActualLRP evacuatingActual *models.ActualLRP afterActual *models.ActualLRP ) BeforeEach(func() { request = nil desiredLRP = model_helpers.NewValidDesiredLRP("the-guid") fakeDesiredLRPDB.DesiredLRPByProcessGuidReturns(desiredLRP, nil) actual = model_helpers.NewValidActualLRP("the-guid", 1) evacuatingActual = model_helpers.NewValidActualLRP("the-guid", 1) afterActual = model_helpers.NewValidActualLRP("the-guid", 1) key := actual.ActualLRPKey
Eventually(func() ([]string, error) { logger := logger.Session("domain-polling") logger.Debug("getting-domains") domains, err := bbsClient.Domains() logger.Debug("finished-getting-domains", lager.Data{"domains": domains, "error": err}) return domains, err }, 2*domainTTL).ShouldNot(ContainElement("cf-apps")) }) }) }) }) Context("when LRPs in a different domain exist", func() { var otherDomainDesired *models.DesiredLRP var otherDomainDesiredResponse *models.DesiredLRP BeforeEach(func() { otherDomainDesired = &models.DesiredLRP{ ProcessGuid: "some-other-lrp", Domain: "some-domain", RootFs: models.PreloadedRootFS("some-stack"), Instances: 1, Action: models.WrapAction(&models.RunAction{ User: "******", Path: "reboot", }), } err := bbsClient.DesireLRP(otherDomainDesired) Expect(err).NotTo(HaveOccurred())
package models_test import ( "encoding/json" "fmt" "github.com/cloudfoundry-incubator/bbs/models" "github.com/gogo/protobuf/proto" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("DesiredLRP", func() { var desiredLRP models.DesiredLRP jsonDesiredLRP := `{ "setup": { "serial": { "actions": [ { "download": { "from": "http://file-server.service.cf.internal:8080/v1/static/buildpack_app_lifecycle/buildpack_app_lifecycle.tgz", "to": "/tmp/lifecycle", "cache_key": "buildpack-cflinuxfs2-lifecycle", "user": "******" } }, { "download": { "from": "http://cloud-controller-ng.service.cf.internal:9022/internal/v2/droplets/some-guid/some-guid/download",
func (t *ETCDHelper) SetRawDesiredLRP(lrp *models.DesiredLRP) { schedulingInfo, runInfo := lrp.Explode() t.SetRawDesiredLRPSchedulingInfo(&schedulingInfo) t.SetRawDesiredLRPRunInfo(&runInfo) }
Context("when there are no actions", func() { BeforeEach(func() { task.Action = nil }) It("does nothing", func() { Expect(migrationErr).NotTo(HaveOccurred()) _, err := db.TaskByGuid(logger, task.TaskGuid) Expect(err).NotTo(HaveOccurred()) }) }) }) Describe("DesiredLRP Migration", func() { var ( processGuid string desiredLRP *models.DesiredLRP ) BeforeEach(func() { processGuid = "process-guid-1" desiredLRP = model_helpers.NewValidDesiredLRP(processGuid) desiredLRP.DeprecatedStartTimeoutS = 15 desiredLRP.Action = models.WrapAction(&models.TimeoutAction{Action: models.WrapAction(&models.RunAction{Path: "ls", User: "******"}), DeprecatedTimeoutNs: 4 * int64(time.Second), }) desiredLRP.Setup = models.WrapAction(&models.TimeoutAction{Action: models.WrapAction(&models.RunAction{Path: "ls", User: "******"}), DeprecatedTimeoutNs: 7 * int64(time.Second), }) desiredLRP.Monitor = models.WrapAction(models.EmitProgressFor( &models.TimeoutAction{
"waffles": "/where/is/the/syrup", "pancakes": "/path/to/lingonberries", })) }) It("errors when passed malformed input", func() { _, err := rep.UnmarshalStackPathMap([]byte(`{"foo": ["bar"]}`)) Expect(err).To(MatchError(ContainSubstring("unmarshal"))) }) }) Describe("NewRunRequestFromDesiredLRP", func() { var ( containerGuid string desiredLRP *models.DesiredLRP actualLRP *models.ActualLRP ) BeforeEach(func() { containerGuid = "the-container-guid" desiredLRP = model_helpers.NewValidDesiredLRP("the-process-guid") actualLRP = model_helpers.NewValidActualLRP("the-process-guid", 9) desiredLRP.RootFs = "preloaded://foobar" }) It("returns a valid run request", func() { runReq, err := rep.NewRunRequestFromDesiredLRP(containerGuid, desiredLRP, &actualLRP.ActualLRPKey, &actualLRP.ActualLRPInstanceKey) Expect(err).NotTo(HaveOccurred()) Expect(runReq.Tags).To(Equal(executor.Tags{})) Expect(runReq.RunInfo).To(Equal(executor.RunInfo{
func DesiredLRPSchemaPath(lrp *models.DesiredLRP) string { return DesiredLRPSchemaPathByProcessGuid(lrp.GetProcessGuid()) }
It("has the correct number of responses", func() { Expect(actualDesiredLRPs).To(HaveLen(2)) }) It("returns only the desired lrps in the requested domain", func() { for _, lrp := range desiredLRPs[domain] { expectedDesiredLRPs = append(expectedDesiredLRPs, lrp) } Expect(actualDesiredLRPs).To(ConsistOf(expectedDesiredLRPs)) }) }) }) Describe("DesiredLRPByProcessGuid", func() { var ( desiredLRP *models.DesiredLRP expectedDesiredLRP *models.DesiredLRP ) JustBeforeEach(func() { expectedDesiredLRP = desiredLRPs["domain-1"][0] desiredLRP, getErr = client.DesiredLRPByProcessGuid(expectedDesiredLRP.GetProcessGuid()) }) It("responds without error", func() { Expect(getErr).NotTo(HaveOccurred()) }) It("returns all desired lrps from the bbs", func() { Expect(desiredLRP).To(Equal(expectedDesiredLRP)) }) })
}) }) Describe("Desired LRPs", func() { var ( existingDesiredLRPs []migrations.ETCDToSQLDesiredLRP desiredLRPsToCreate int ) BeforeEach(func() { encoder := format.NewEncoder(cryptor) desiredLRPsToCreate = 3 for i := 0; i < desiredLRPsToCreate; i++ { processGuid := fmt.Sprintf("process-guid-%d", i) var desiredLRP *models.DesiredLRP desiredLRP = model_helpers.NewValidDesiredLRP(processGuid) schedulingInfo, runInfo := desiredLRP.CreateComponents(fakeClock.Now()) var ( encryptedVolumePlacement []byte err error ) if i == 0 { // test for nil and full VolumePlacements schedulingInfo.VolumePlacement = nil encryptedVolumePlacement, err = serializer.Marshal(logger, format.ENCRYPTED_PROTO, &models.VolumePlacement{}) } else { encryptedVolumePlacement, err = serializer.Marshal(logger, format.ENCRYPTED_PROTO, schedulingInfo.VolumePlacement) } Expect(err).NotTo(HaveOccurred())