func (factory *DockerRunnerCommandFactory) createApp(context *cli.Context) { workingDirFlag := context.String("working-dir") envVarsFlag := context.StringSlice("env") instancesFlag := context.Int("instances") cpuWeightFlag := uint(context.Int("cpu-weight")) memoryMBFlag := context.Int("memory-mb") diskMBFlag := context.Int("disk-mb") portsFlag := context.String("ports") runAsRootFlag := context.Bool("run-as-root") noMonitorFlag := context.Bool("no-monitor") portMonitorFlag := context.Int("monitor-port") urlMonitorFlag := context.String("monitor-url") monitorTimeoutFlag := context.Duration("monitor-timeout") routesFlag := context.String("routes") noRoutesFlag := context.Bool("no-routes") timeoutFlag := context.Duration("timeout") name := context.Args().Get(0) dockerPath := context.Args().Get(1) terminator := context.Args().Get(2) startCommand := context.Args().Get(3) var appArgs []string switch { case len(context.Args()) < 2: factory.UI.SayIncorrectUsage("APP_NAME and DOCKER_IMAGE are required") factory.ExitHandler.Exit(exit_codes.InvalidSyntax) return case startCommand != "" && terminator != "--": factory.UI.SayIncorrectUsage("'--' Required before start command") factory.ExitHandler.Exit(exit_codes.InvalidSyntax) return case len(context.Args()) > 4: appArgs = context.Args()[4:] case cpuWeightFlag < 1 || cpuWeightFlag > 100: factory.UI.SayIncorrectUsage("Invalid CPU Weight") factory.ExitHandler.Exit(exit_codes.InvalidSyntax) return } imageMetadata, err := factory.dockerMetadataFetcher.FetchMetadata(dockerPath) if err != nil { factory.UI.Say(fmt.Sprintf("Error fetching image metadata: %s", err)) factory.ExitHandler.Exit(exit_codes.BadDocker) return } exposedPorts, err := factory.getExposedPortsFromArgs(portsFlag, imageMetadata) if err != nil { factory.UI.Say(err.Error()) factory.ExitHandler.Exit(exit_codes.InvalidSyntax) return } monitorConfig, err := factory.GetMonitorConfig(exposedPorts, portMonitorFlag, noMonitorFlag, urlMonitorFlag, monitorTimeoutFlag) if err != nil { factory.UI.Say(err.Error()) if err.Error() == command_factory.MonitorPortNotExposed { factory.ExitHandler.Exit(exit_codes.CommandFailed) } else { factory.ExitHandler.Exit(exit_codes.InvalidSyntax) } return } if workingDirFlag == "" { factory.UI.Say("No working directory specified, using working directory from the image metadata...\n") if imageMetadata.WorkingDir != "" { workingDirFlag = imageMetadata.WorkingDir factory.UI.Say("Working directory is:\n") factory.UI.Say(workingDirFlag + "\n") } else { workingDirFlag = "/" } } if !noMonitorFlag { factory.UI.Say(fmt.Sprintf("Monitoring the app on port %d...\n", monitorConfig.Port)) } else { factory.UI.Say("No ports will be monitored.\n") } if startCommand == "" { if len(imageMetadata.StartCommand) == 0 { factory.UI.SayLine("Unable to determine start command from image metadata.") factory.ExitHandler.Exit(exit_codes.BadDocker) return } factory.UI.Say("No start command specified, using start command from the image metadata...\n") startCommand = imageMetadata.StartCommand[0] factory.UI.Say("Start command is:\n") factory.UI.Say(strings.Join(imageMetadata.StartCommand, " ") + "\n") appArgs = imageMetadata.StartCommand[1:] } routeOverrides, err := factory.ParseRouteOverrides(routesFlag) if err != nil { factory.UI.Say(err.Error()) factory.ExitHandler.Exit(exit_codes.InvalidSyntax) return } rootFS, err := docker_repository_name_formatter.FormatForReceptor(dockerPath) if err != nil { factory.UI.Say(err.Error()) factory.ExitHandler.Exit(exit_codes.CommandFailed) return } err = factory.AppRunner.CreateApp(app_runner.CreateAppParams{ AppEnvironmentParams: app_runner.AppEnvironmentParams{ EnvironmentVariables: factory.BuildEnvironment(envVarsFlag, name), Privileged: runAsRootFlag, Monitor: monitorConfig, Instances: instancesFlag, CPUWeight: cpuWeightFlag, MemoryMB: memoryMBFlag, DiskMB: diskMBFlag, ExposedPorts: exposedPorts, WorkingDir: workingDirFlag, RouteOverrides: routeOverrides, NoRoutes: noRoutesFlag, }, Name: name, RootFS: rootFS, StartCommand: startCommand, AppArgs: appArgs, Timeout: timeoutFlag, Setup: &models.DownloadAction{ From: "http://file_server.service.dc1.consul:8080/v1/static/healthcheck.tgz", To: "/tmp", }, }) if err != nil { factory.UI.Say(fmt.Sprintf("Error creating app: %s", err)) factory.ExitHandler.Exit(exit_codes.CommandFailed) return } factory.WaitForAppCreation(name, timeoutFlag, instancesFlag, noRoutesFlag, routeOverrides) }
package docker_repository_name_formatter_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/cloudfoundry-incubator/lattice/ltc/docker_runner/docker_repository_name_formatter" ) var _ = Describe("DockerRepositoryNameFormatter", func() { Describe("FormatForReceptor", func() { Context("with a well-formed docker repo name", func() { Context("with a fully qualified docker repo name", func() { It("Formats it as a url that the receptor can use as a rootfs", func() { formattedName, err := docker_repository_name_formatter.FormatForReceptor("jimbo/my-docker-app") Expect(err).NotTo(HaveOccurred()) Expect(formattedName).To(Equal("docker:///jimbo/my-docker-app#latest")) }) Context("when a tag is specified", func() { It("Converts it to a tagged url that receptor can use as a rootfs", func() { formattedName, err := docker_repository_name_formatter.FormatForReceptor("jimbo/my-docker-app:test") Expect(err).NotTo(HaveOccurred()) Expect(formattedName).To(Equal("docker:///jimbo/my-docker-app#test")) }) }) }) Context("with a shortened official docker repo name", func() { It("Formats it as a url that the receptor can use as a rootfs", func() {