Beispiel #1
0
func (appRunner *appRunner) desireLrp(params CreateAppParams) error {
	primaryPort := route_helpers.GetPrimaryPort(params.Monitor.Port, params.ExposedPorts)

	private, public, err := appRunner.keygen.GenerateRSAKeyPair(2048)
	if err != nil {
		return err
	}

	routes := appRunner.buildRoutesWithDefaults(params, primaryPort)
	routes.DiegoSSHRoute = &route_helpers.DiegoSSHRoute{
		Port:       2222,
		PrivateKey: private,
	}

	vcapAppURIs := []string{}
	for _, route := range routes.AppRoutes {
		vcapAppURIs = append(vcapAppURIs, route.Hostnames...)
	}

	vcapApplication := struct {
		ApplicationName string   `json:"application_name"`
		ApplicationURIs []string `json:"application_uris"`
		Name            string   `json:"name"`
		URIs            []string `json:"uris"`
		Limits          struct {
			Disk   int `json:"disk,omitempty"`
			Memory int `json:"mem,omitempty"`
		} `json:"limits,omitempty"`
	}{}

	vcapApplication.ApplicationName = params.Name
	vcapApplication.Name = params.Name
	vcapApplication.ApplicationURIs = vcapAppURIs
	vcapApplication.URIs = vcapAppURIs
	vcapApplication.Limits.Disk = params.DiskMB
	vcapApplication.Limits.Memory = params.MemoryMB

	vcapAppBytes, err := json.Marshal(vcapApplication)
	if err != nil {
		return err
	}

	envVars := buildEnvironmentVariables(params.EnvironmentVariables)
	envVars = append(envVars, receptor.EnvironmentVariable{Name: "VCAP_APPLICATION", Value: string(vcapAppBytes)})
	envVars = append(envVars, receptor.EnvironmentVariable{Name: "PORT", Value: fmt.Sprintf("%d", primaryPort)})

	if _, exists := params.EnvironmentVariables["VCAP_SERVICES"]; !exists {
		envVars = append(envVars, receptor.EnvironmentVariable{Name: "VCAP_SERVICES", Value: "{}"})
	}

	var setupAction *models.Action
	if params.Setup != nil {
		setupAction = models.WrapAction(&models.SerialAction{
			Actions: []*models.Action{
				params.Setup,
				models.WrapAction(&models.DownloadAction{
					From: "http://file-server.service.cf.internal:8080/v1/static/buildpack_app_lifecycle/buildpack_app_lifecycle.tgz",
					To:   "/tmp",
					User: params.User,
				}),
			}})
	} else {
		setupAction = models.WrapAction(&models.DownloadAction{
			From: "http://file-server.service.cf.internal:8080/v1/static/buildpack_app_lifecycle/buildpack_app_lifecycle.tgz",
			To:   "/tmp",
			User: params.User,
		})
	}

	hostKey, err := appRunner.keygen.GenerateRSAPrivateKey(2048)
	if err != nil {
		return err
	}

	req := receptor.DesiredLRPCreateRequest{
		ProcessGuid:          params.Name,
		Domain:               "lattice",
		RootFS:               params.RootFS,
		Instances:            params.Instances,
		Routes:               routes.RoutingInfo(),
		CPUWeight:            params.CPUWeight,
		MemoryMB:             params.MemoryMB,
		DiskMB:               params.DiskMB,
		Privileged:           params.Privileged,
		Ports:                append(params.ExposedPorts, 2222),
		LogGuid:              params.Name,
		LogSource:            "APP",
		MetricsGuid:          params.Name,
		EnvironmentVariables: envVars,
		Annotation:           params.Annotation,
		Setup:                setupAction,
		Action: &models.Action{
			ParallelAction: &models.ParallelAction{
				Actions: []*models.Action{
					models.WrapAction(&models.RunAction{
						Path: "/tmp/diego-sshd",
						Args: []string{
							"-address=0.0.0.0:2222",
							fmt.Sprintf("-authorizedKey=%s", public),
							fmt.Sprintf("-hostKey=%s", hostKey),
						},
						Dir:  "/tmp",
						User: params.User,
					}),
					models.WrapAction(&models.RunAction{
						Path: params.StartCommand,
						Args: params.AppArgs,
						Dir:  params.WorkingDir,
						User: params.User,
					}),
				},
			},
		},
	}

	var healthCheckArgs []string
	if params.Monitor.Timeout != 0 {
		healthCheckArgs = append(healthCheckArgs, "-timeout", fmt.Sprint(params.Monitor.Timeout))
	}
	switch params.Monitor.Method {
	case PortMonitor:
		req.Monitor = &models.Action{
			RunAction: &models.RunAction{
				Path:      "/tmp/healthcheck",
				Args:      append(healthCheckArgs, "-port", fmt.Sprint(params.Monitor.Port)),
				LogSource: "HEALTH",
				User:      params.User,
			},
		}
	case URLMonitor:
		req.Monitor = &models.Action{
			RunAction: &models.RunAction{
				Path:      "/tmp/healthcheck",
				Args:      append(healthCheckArgs, "-port", fmt.Sprint(params.Monitor.Port), "-uri", params.Monitor.URI),
				LogSource: "HEALTH",
				User:      params.User,
			},
		}
	case CustomMonitor:
		req.Monitor = &models.Action{
			RunAction: &models.RunAction{
				Path:      "/bin/sh",
				Args:      []string{"-c", params.Monitor.CustomCommand},
				LogSource: "HEALTH",
				User:      params.User,
			},
		}
	}

	return appRunner.receptorClient.CreateDesiredLRP(req)
}
				})

				It("panics", func() {
					routesFromRoutingInfo := func() func() {
						return func() { route_helpers.RoutesFromRoutingInfo(routingInfo) }
					}
					Consistently(routesFromRoutingInfo).Should(Panic(), "invalid json.RawMessage ought to panic")
				})
			})
		})
	})

	Describe("GetPrimaryPort", func() {
		Context("when there is no monitor port, but exposedPorts are empty", func() {
			It("return 0", func() {
				returnPort := route_helpers.GetPrimaryPort(uint16(0), []uint16{})
				Expect(returnPort).To(BeZero())
			})
		})

		Context("when there is monitor port, and exposedPorts are not empty", func() {
			It("return the first exposed port", func() {
				returnPort := route_helpers.GetPrimaryPort(uint16(0), []uint16{2000, 3000})
				Expect(returnPort).To(Equal(uint16(2000)))
			})
		})

		Context("when there is monitor port", func() {
			It("return the monitor port", func() {
				returnPort := route_helpers.GetPrimaryPort(uint16(1000), []uint16{2000, 3000})
				Expect(returnPort).To(Equal(uint16(1000)))