expectedAction := models.Codependent(
						&models.RunAction{
							User: "******",
							Path: "/tmp/lifecycle/launcher",
							Args: []string{
								"app",
								"the-start-command with-arguments",
								"the-execution-metadata",
							},
							Env: []*models.EnvironmentVariable{
								{Name: "foo", Value: "bar"},
								{Name: "PORT", Value: "8080"},
							},
							ResourceLimits: &models.ResourceLimits{
								Nofile: &expectedNumFiles,
							},
							LogSource: "APP",
						},
						&models.RunAction{
							User: "******",
							Path: "/tmp/lifecycle/diego-sshd",
							Args: []string{
								"-address=0.0.0.0:2222",
								"-hostKey=pem-host-private-key",
								"-authorizedKey=authorized-user-key",
								"-inheritDaemonEnv",
								"-logLevel=fatal",
							},
							Env: []*models.EnvironmentVariable{
								{Name: "foo", Value: "bar"},
								{Name: "PORT", Value: "8080"},
							},
							ResourceLimits: &models.ResourceLimits{
								Nofile: &expectedNumFiles,
							},
						},
					)
Esempio n. 2
0
						},
						{
							"run": {
								"resource_limits": {},
								"path": "echo",
								"user": "******",
								"suppress_log_output": false
							}
						}
					]
			}`,
			models.WrapAction(models.Codependent(
				&models.DownloadAction{
					From:     "web_location",
					To:       "local_location",
					CacheKey: "elephant",
					User:     "******",
				},
				&models.RunAction{Path: "echo", User: "******", ResourceLimits: &models.ResourceLimits{}},
			)),
		)

		Describe("Validate", func() {
			var codependentAction *models.CodependentAction

			Context("when the action has 'actions' as a slice of valid actions", func() {
				It("is valid", func() {
					codependentAction = models.Codependent(
						&models.UploadAction{
							From: "local_location",
							To:   "web_location",
func (b *BuildpackRecipeBuilder) Build(desiredApp *cc_messages.DesireAppRequestFromCC) (*models.DesiredLRP, error) {
	lrpGuid := desiredApp.ProcessGuid

	buildLogger := b.logger.Session("message-builder")

	if desiredApp.DropletUri == "" {
		buildLogger.Error("desired-app-invalid", ErrDropletSourceMissing, lager.Data{"desired-app": desiredApp})
		return nil, ErrDropletSourceMissing
	}

	if desiredApp.DropletUri != "" && desiredApp.DockerImageUrl != "" {
		buildLogger.Error("desired-app-invalid", ErrMultipleAppSources, lager.Data{"desired-app": desiredApp})
		return nil, ErrMultipleAppSources
	}

	var lifecycle = "buildpack/" + desiredApp.Stack
	lifecyclePath, ok := b.config.Lifecycles[lifecycle]
	if !ok {
		buildLogger.Error("unknown-lifecycle", ErrNoLifecycleDefined, lager.Data{
			"lifecycle": lifecycle,
		})

		return nil, ErrNoLifecycleDefined
	}

	lifecycleURL := lifecycleDownloadURL(lifecyclePath, b.config.FileServerURL)

	rootFSPath := models.PreloadedRootFS(desiredApp.Stack)

	var containerEnvVars []*models.EnvironmentVariable
	containerEnvVars = append(containerEnvVars, &models.EnvironmentVariable{"LANG", DefaultLANG})

	numFiles := DefaultFileDescriptorLimit
	if desiredApp.FileDescriptors != 0 {
		numFiles = desiredApp.FileDescriptors
	}

	var setup []models.ActionInterface
	var actions []models.ActionInterface
	var monitor models.ActionInterface

	cachedDependencies := []*models.CachedDependency{}
	cachedDependencies = append(cachedDependencies, &models.CachedDependency{
		From:     lifecycleURL,
		To:       "/tmp/lifecycle",
		CacheKey: fmt.Sprintf("%s-lifecycle", strings.Replace(lifecycle, "/", "-", 1)),
	})

	desiredAppPorts, err := b.ExtractExposedPorts(desiredApp)
	if err != nil {
		return nil, err
	}

	switch desiredApp.HealthCheckType {
	case cc_messages.PortHealthCheckType, cc_messages.UnspecifiedHealthCheckType:
		monitor = models.Timeout(getParallelAction(desiredAppPorts, "vcap"), 30*time.Second)
	}

	setup = append(setup, &models.DownloadAction{
		From:     desiredApp.DropletUri,
		To:       ".",
		CacheKey: fmt.Sprintf("droplets-%s", lrpGuid),
		User:     "******",
	})

	actions = append(actions, &models.RunAction{
		User: "******",
		Path: "/tmp/lifecycle/launcher",
		Args: append(
			[]string{"app"},
			desiredApp.StartCommand,
			desiredApp.ExecutionMetadata,
		),
		Env:       createLrpEnv(desiredApp.Environment, desiredAppPorts[0]),
		LogSource: AppLogSource,
		ResourceLimits: &models.ResourceLimits{
			Nofile: &numFiles,
		},
	})

	desiredAppRoutingInfo, err := helpers.CCRouteInfoToRoutes(desiredApp.RoutingInfo, desiredAppPorts)
	if err != nil {
		buildLogger.Error("marshaling-cc-route-info-failed", err)
		return nil, err
	}

	if desiredApp.AllowSSH {
		hostKeyPair, err := b.config.KeyFactory.NewKeyPair(1024)
		if err != nil {
			buildLogger.Error("new-host-key-pair-failed", err)
			return nil, err
		}

		userKeyPair, err := b.config.KeyFactory.NewKeyPair(1024)
		if err != nil {
			buildLogger.Error("new-user-key-pair-failed", err)
			return nil, err
		}

		actions = append(actions, &models.RunAction{
			User: "******",
			Path: "/tmp/lifecycle/diego-sshd",
			Args: []string{
				"-address=" + fmt.Sprintf("0.0.0.0:%d", DefaultSSHPort),
				"-hostKey=" + hostKeyPair.PEMEncodedPrivateKey(),
				"-authorizedKey=" + userKeyPair.AuthorizedKey(),
				"-inheritDaemonEnv",
				"-logLevel=fatal",
			},
			Env: createLrpEnv(desiredApp.Environment, desiredAppPorts[0]),
			ResourceLimits: &models.ResourceLimits{
				Nofile: &numFiles,
			},
		})

		sshRoutePayload, err := json.Marshal(ssh_routes.SSHRoute{
			ContainerPort:   2222,
			PrivateKey:      userKeyPair.PEMEncodedPrivateKey(),
			HostFingerprint: hostKeyPair.Fingerprint(),
		})

		if err != nil {
			buildLogger.Error("marshaling-ssh-route-failed", err)
			return nil, err
		}

		sshRouteMessage := json.RawMessage(sshRoutePayload)
		desiredAppRoutingInfo[ssh_routes.DIEGO_SSH] = &sshRouteMessage
		desiredAppPorts = append(desiredAppPorts, DefaultSSHPort)
	}

	setupAction := models.Serial(setup...)
	actionAction := models.Codependent(actions...)

	return &models.DesiredLRP{
		Privileged: true,

		Domain: cc_messages.AppLRPDomain,

		ProcessGuid: lrpGuid,
		Instances:   int32(desiredApp.NumInstances),
		Routes:      &desiredAppRoutingInfo,
		Annotation:  desiredApp.ETag,

		CpuWeight: cpuWeight(desiredApp.MemoryMB),

		MemoryMb: int32(desiredApp.MemoryMB),
		DiskMb:   int32(desiredApp.DiskMB),

		Ports: desiredAppPorts,

		RootFs: rootFSPath,

		LogGuid:   desiredApp.LogGuid,
		LogSource: LRPLogSource,

		MetricsGuid: desiredApp.LogGuid,

		EnvironmentVariables: containerEnvVars,
		CachedDependencies:   cachedDependencies,
		Setup:                models.WrapAction(setupAction),
		Action:               models.WrapAction(actionAction),
		Monitor:              models.WrapAction(monitor),

		StartTimeout: uint32(desiredApp.HealthCheckTimeoutInSeconds),

		EgressRules:        desiredApp.EgressRules,
		LegacyDownloadUser: "******",
	}, nil
}
Esempio n. 4
0
				Eventually(desiredLRPsWithoutModificationTag).Should(ContainElement(&models.DesiredLRP{
					ProcessGuid:  "process-guid-1",
					Domain:       "cf-apps",
					Instances:    42,
					RootFs:       models.PreloadedRootFS("some-stack"),
					Setup:        models.WrapAction(expectedSetupActions1),
					StartTimeout: 123456,
					EnvironmentVariables: []*models.EnvironmentVariable{
						{Name: "LANG", Value: recipebuilder.DefaultLANG},
					},
					Action: models.WrapAction(models.Codependent(&models.RunAction{
						User: "******",
						Path: "/tmp/lifecycle/launcher",
						Args: []string{"app", "start-command-1", "execution-metadata-1"},
						Env: []*models.EnvironmentVariable{
							{Name: "env-key-1", Value: "env-value-1"},
							{Name: "env-key-2", Value: "env-value-2"},
							{Name: "PORT", Value: "8080"},
						},
						ResourceLimits: &models.ResourceLimits{Nofile: &nofile},
						LogSource:      recipebuilder.AppLogSource,
					})),
					Monitor: models.WrapAction(models.Timeout(
						&models.ParallelAction{
							Actions: []*models.Action{
								&models.Action{
									RunAction: &models.RunAction{
										User:      "******",
										Path:      "/tmp/lifecycle/healthcheck",
										Args:      []string{"-port=8080"},
										LogSource: "HEALTH",
										ResourceLimits: &models.ResourceLimits{
Esempio n. 5
0
							}
						},
						{
							"run": {
								"resource_limits": {},
								"path": "echo",
								"user": "******"
							}
						}
					]
			}`,
			models.Codependent(
				&models.DownloadAction{
					From:     "web_location",
					To:       "local_location",
					CacheKey: "elephant",
					User:     "******",
				},
				&models.RunAction{Path: "echo", User: "******", ResourceLimits: &models.ResourceLimits{}},
			),
		)

		itSerializesAndDeserializes(
			`{}`,
			models.WrapAction(&models.CodependentAction{}),
		)

		itSerializesAndDeserializes(
			`{
				"actions": [null]
			}`,