func (runner *clusterTestRunner) cloneRepo(timeout time.Duration, repoURL string) string {
	tmpDir, err := ioutil.TempDir("", "repo")
	Expect(err).NotTo(HaveOccurred())

	fmt.Fprintln(getStyledWriter("test"), colors.PurpleUnderline(fmt.Sprintf("Attempting to clone %s to %s", repoURL, tmpDir)))

	command := exec.Command("git", "clone", repoURL, tmpDir)
	session, err := gexec.Start(command, getStyledWriter("git-clone"), getStyledWriter("git-clone"))
	Expect(err).NotTo(HaveOccurred())

	expectExitInBuffer(timeout, session, session.Err)
	Eventually(session.Err).Should(test_helpers.Say(fmt.Sprintf("Cloning into '%s'...", tmpDir)))

	fmt.Fprintf(getStyledWriter("test"), "Cloned %s into %s\n", repoURL, tmpDir)

	return tmpDir
}
		logReader = fake_log_reader.NewFakeLogReader()
		consoleTailedLogsOutputter = console_tailed_logs_outputter.NewConsoleTailedLogsOutputter(terminalUI, logReader)
	})

	Describe("OutputTailedLogs", func() {
		It("Tails logs", func() {
			now := time.Now()
			logReader.AddLog(buildLogMessage("RTR", "1", now, []byte("First log")))
			logReader.AddError(errors.New("First Error"))

			go consoleTailedLogsOutputter.OutputTailedLogs("my-app-guid")

			Eventually(logReader.GetAppGuid).Should(Equal("my-app-guid"))

			logOutputBufferString := fmt.Sprintf("%s [%s|%s] First log\n", colors.Cyan(now.Format("01/02 15:04:05.00")), colors.Yellow("RTR"), colors.Yellow("1"))
			Eventually(outputBuffer).Should(test_helpers.Say(logOutputBufferString))
			Eventually(outputBuffer).Should(test_helpers.Say("First Error\n"))
		})
	})

	Describe("OutputDebugLogs", func() {
		It("tails logs with pretty formatting", func() {
			now := time.Now()
			logReader.AddLog(buildLogMessage("rep", "cell-1", now, []byte("First log")))
			logReader.AddError(errors.New("First Error"))

			go consoleTailedLogsOutputter.OutputDebugLogs(true)

			Eventually(logReader.GetAppGuid).Should(Equal(reserved_app_ids.LatticeDebugLogStreamAppId))

			Eventually(outputBuffer).Should(test_helpers.Say("rep"))
示例#3
0
	Describe("MakeCliApp", func() {
		It("makes an app", func() {
			Expect(cliApp).ToNot(BeNil())
			Expect(cliApp.Name).To(Equal("ltc"))
			Expect(cliApp.Author).To(Equal("Pivotal"))
			Expect(cliApp.Version).To(Equal("v0.2.Test (diego 0.12345.0)"))
			Expect(cliApp.Email).To(Equal("*****@*****.**"))
			Expect(cliApp.Usage).To(Equal(cli_app_factory.LtcUsage))
			Expect(cliApp.Commands).NotTo(BeEmpty())
			Expect(cliApp.Action).ToNot(BeNil())
			Expect(cliApp.CommandNotFound).ToNot(BeNil())

			By("writing to the App.Writer", func() {
				cliApp.Writer.Write([]byte("write_sample"))
				Expect(outputBuffer).To(test_helpers.Say("write_sample"))
			})

		})

		Context("when targeted at a dav blob store", func() {
			BeforeEach(func() {
				cliConfig.SetBlobStore("http://test.com", "9999", "username", "password")
			})

			It("instantiates a new dav blob store object", func() {

			})
		})

		Context("when invoked without latticeVersion set", func() {
示例#4
0
				test_helpers.ExecuteCommandWithArgs(sshCommand, []string{"-t", "app-name", "/bin/ls"})

				Expect(fakeSSH.ShellCallCount()).To(Equal(1))
				_, ptyDesired := fakeSSH.ShellArgsForCall(0)
				Expect(ptyDesired).To(BeTrue())
			})

			Context("when a command is provided", func() {
				It("should run a command remotely instead of the login shell", func() {
					fakeAppExaminer.AppStatusReturns(app_examiner.AppInfo{ActualRunningInstances: 1}, nil)

					doneChan := test_helpers.AsyncExecuteCommandWithArgs(sshCommand, []string{"app-name", "echo", "1", "2", "3"})

					Eventually(doneChan, 3).Should(BeClosed())
					Expect(outputBuffer).NotTo(test_helpers.Say("Connecting to app-name"))

					Expect(fakeSSH.ShellCallCount()).To(Equal(1))
					command, _ := fakeSSH.ShellArgsForCall(0)
					Expect(command).To(Equal("echo 1 2 3"))
				})

				It("should support -- delimiter for args", func() {
					fakeAppExaminer.AppStatusReturns(app_examiner.AppInfo{ActualRunningInstances: 1}, nil)

					test_helpers.ExecuteCommandWithArgs(sshCommand, []string{"app-name", "--", "/bin/ls", "-l"})

					Expect(fakeSSH.ShellCallCount()).To(Equal(1))
					command, _ := fakeSSH.ShellArgsForCall(0)
					Expect(command).To(Equal("/bin/ls -l"))
				})
		It("is an error when no path is passed in", func() {
			test_helpers.ExecuteCommandWithArgs(submitTaskCommand, []string{})

			Expect(outputBuffer).To(test_helpers.SayLine("Path to JSON is required"))
			Expect(fakeTaskRunner.SubmitTaskCallCount()).To(BeZero())
			Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.InvalidSyntax}))
		})

		Context("when the file cannot be read", func() {
			It("prints an error", func() {
				args := []string{filepath.Join(os.TempDir(), "file-no-existy")}

				test_helpers.ExecuteCommandWithArgs(submitTaskCommand, args)

				Expect(outputBuffer).To(test_helpers.Say("Error reading file"))
				Expect(fakeTaskRunner.SubmitTaskCallCount()).To(Equal(0))
				Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.FileSystemError}))
			})
		})

	})

	Describe("DeleteTaskCommand", func() {
		var deleteTaskCommand cli.Command

		BeforeEach(func() {
			commandFactory := command_factory.NewTaskRunnerCommandFactory(fakeTaskRunner, terminalUI, fakeExitHandler)
			deleteTaskCommand = commandFactory.MakeDeleteTaskCommand()
		})
示例#6
0
	})

	Describe("Instantiation", func() {
		It("instantiates a terminal", func() {
			Expect(terminalUI).NotTo(BeNil())

			_, readWriterOk := terminalUI.(io.ReadWriter)
			Expect(readWriterOk).To(BeTrue())
		})
	})

	Describe("Output methods", func() {
		Describe("Say", func() {
			It("says the message to the terminal", func() {
				terminalUI.Say("Cloudy with a chance of meatballs")
				Expect(outputBuffer).To(test_helpers.Say("Cloudy with a chance of meatballs"))
			})

			Context("when printf-style syntax is used", func() {
				It("says the formatted message to the terminal", func() {
					terminalUI.Say("delim %s what %d", "put-this-in", 44)
					Expect(outputBuffer).To(test_helpers.Say("delim put-this-in what 44"))
				})
			})
		})

		Describe("SayLine", func() {
			It("says the message to the terminal with a newline", func() {
				terminalUI.SayLine("Strange Clouds")
				Expect(outputBuffer).To(test_helpers.Say("Strange Clouds\n"))
			})
				Expect(fakeDockerMetadataFetcher.FetchMetadataArgsForCall(0)).To(Equal("fun-org/app"))

				Expect(fakeAppRunner.CreateAppCallCount()).To(Equal(1))
				createAppParams := fakeAppRunner.CreateAppArgsForCall(0)
				Expect(createAppParams.StartCommand).To(Equal("/fetch-start"))
				Expect(createAppParams.AppArgs).To(Equal([]string{"arg1", "arg2"}))
				Expect(createAppParams.RootFS).To(Equal("docker:///fun-org/app#latest"))
				Expect(createAppParams.WorkingDir).To(Equal("/this/directory/right/here"))
			})

			It("does not output the working directory if it is not set", func() {
				fakeDockerMetadataFetcher.FetchMetadataReturns(&docker_metadata_fetcher.ImageMetadata{StartCommand: []string{"/fetch-start"}}, nil)

				test_helpers.ExecuteCommandWithArgs(createCommand, args)

				Expect(outputBuffer).NotTo(test_helpers.Say("Working directory is:"))
				Expect(fakeAppRunner.CreateAppCallCount()).To(Equal(1))
			})

			Context("when the metadata also has no start command", func() {
				It("outputs an error message and exits", func() {
					fakeDockerMetadataFetcher.FetchMetadataReturns(&docker_metadata_fetcher.ImageMetadata{}, nil)

					test_helpers.ExecuteCommandWithArgs(createCommand, args)

					Expect(outputBuffer).To(test_helpers.SayLine("Unable to determine start command from image metadata."))
					Expect(fakeAppRunner.CreateAppCallCount()).To(Equal(0))
					Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.BadDocker}))
				})
			})
		})
		})

		It("displays info for a pending task", func() {
			taskInfo := task_examiner.TaskInfo{
				TaskGuid:      "boop",
				State:         "PENDING",
				CellID:        "cell-01",
				Failed:        false,
				FailureReason: "",
				Result:        "",
			}
			fakeTaskExaminer.TaskStatusReturns(taskInfo, nil)

			test_helpers.ExecuteCommandWithArgs(taskCommand, []string{"boop"})

			Expect(outputBuffer).To(test_helpers.Say("Task GUID"))
			Expect(outputBuffer).To(test_helpers.Say("boop"))
			Expect(outputBuffer).To(test_helpers.Say("Cell ID"))
			Expect(outputBuffer).To(test_helpers.Say("cell-01"))
			Expect(outputBuffer).To(test_helpers.Say("Status"))
			Expect(outputBuffer).To(test_helpers.Say(colors.Yellow("PENDING")))
			Expect(outputBuffer).NotTo(test_helpers.Say("Result"))
			Expect(outputBuffer).NotTo(test_helpers.Say("Failure Reason"))
			Expect(outputBuffer).To(test_helpers.SayNewLine())

			Expect(fakeTaskExaminer.TaskStatusCallCount()).To(Equal(1))
			Expect(fakeTaskExaminer.TaskStatusArgsForCall(0)).To(Equal("boop"))
		})

		It("displays result for a non-failed completed task", func() {
			taskInfo := task_examiner.TaskInfo{
				Expect(uploadPath).NotTo(BeNil())
				Expect(uploadPath).To(Equal("xyz.zip"))
			})

			It("passes through environment variables from the command-line", func() {
				args := []string{
					"-e",
					"AAAA",
					"-e",
					"BBBB=2",
					"droplet-name",
					"http://some.url/for/buildpack",
				}
				test_helpers.ExecuteCommandWithArgs(buildDropletCommand, args)

				Expect(outputBuffer).To(test_helpers.Say("Submitted build of droplet-name"))

				_, _, _, envVars, _, _, _ := fakeDropletRunner.BuildDropletArgsForCall(0)

				aaaaVar, found := envVars["AAAA"]
				Expect(found).To(BeTrue())
				Expect(aaaaVar).To(Equal("xyz"))
				bbbbVar, found := envVars["BBBB"]
				Expect(found).To(BeTrue())
				Expect(bbbbVar).To(Equal("2"))
			})

			It("allows specifying resource parameters on the command-line", func() {
				args := []string{
					"-c",
					"75",
		})

		It("is an error when no path is passed in", func() {
			test_helpers.ExecuteCommandWithArgs(submitLrpCommand, []string{})

			Expect(outputBuffer).To(test_helpers.SayLine("Path to JSON is required"))
			Expect(fakeAppRunner.SubmitLrpCallCount()).To(BeZero())
			Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.InvalidSyntax}))
		})

		Context("when the file cannot be read", func() {
			It("prints an error", func() {
				args := []string{"file-no-existy"}
				test_helpers.ExecuteCommandWithArgs(submitLrpCommand, args)

				Expect(outputBuffer).To(test_helpers.Say("Error reading file: open file-no-existy:"))
				Expect(fakeAppRunner.SubmitLrpCallCount()).To(Equal(0))
				Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.FileSystemError}))
			})
		})
	})

	Describe("ScaleAppCommand", func() {
		var scaleCommand cli.Command

		BeforeEach(func() {
			appRunnerCommandFactoryConfig = command_factory.AppRunnerCommandFactoryConfig{
				AppRunner:   fakeAppRunner,
				AppExaminer: fakeAppExaminer,
				UI:          terminalUI,
				Clock:       fakeClock,
		It("polls until the required number of instances are running", func() {
			fakeAppExaminer.RunningAppInstancesInfoReturns(1, false, nil)

			args := []string{
				"cool-web-app",
				"22",
			}
			doneChan := test_helpers.AsyncExecuteCommandWithArgs(scaleCommand, args)

			Eventually(outputBuffer).Should(test_helpers.SayLine("Scaling cool-web-app to 22 instances"))

			Expect(fakeAppExaminer.RunningAppInstancesInfoCallCount()).To(Equal(1))
			Expect(fakeAppExaminer.RunningAppInstancesInfoArgsForCall(0)).To(Equal("cool-web-app"))

			fakeClock.IncrementBySeconds(1)
			Eventually(outputBuffer).Should(test_helpers.Say("."))
			fakeClock.IncrementBySeconds(1)
			Eventually(outputBuffer).Should(test_helpers.Say("."))

			fakeAppExaminer.RunningAppInstancesInfoReturns(22, false, nil)
			fakeClock.IncrementBySeconds(1)

			Eventually(doneChan, 3).Should(BeClosed())

			Expect(outputBuffer).To(test_helpers.SayLine(colors.Green("App Scaled Successfully")))
		})

		Context("when the app does not scale before the timeout elapses", func() {
			It("alerts the user the app took too long to scale", func() {
				fakeAppExaminer.RunningAppInstancesInfoReturns(1, false, nil)
					Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.FileSystemError}))
				})
			})
		})

		Context("when the receptor requires authentication", func() {
			BeforeEach(func() {
				fakeTargetVerifier.VerifyTargetReturns(true, false, nil)
				fakeBlobStoreVerifier.VerifyReturns(true, nil)
				fakePasswordReader.PromptForPasswordReturns("testpassword")
			})

			It("prompts for credentials and stores them in the config", func() {
				doneChan := test_helpers.AsyncExecuteCommandWithArgs(targetCommand, []string{"myapi.com"})

				Eventually(outputBuffer).Should(test_helpers.Say("Username: "******"testusername\n"))

				Eventually(doneChan, 3).Should(BeClosed())

				Expect(config.Target()).To(Equal("myapi.com"))
				Expect(config.Receptor()).To(Equal("http://*****:*****@receptor.myapi.com"))
				Expect(outputBuffer).To(test_helpers.SayLine("API location set."))

				Expect(fakePasswordReader.PromptForPasswordCallCount()).To(Equal(1))
				Expect(fakePasswordReader.PromptForPasswordArgsForCall(0)).To(Equal("Password"))

				Expect(fakeTargetVerifier.VerifyTargetCallCount()).To(Equal(2))
				Expect(fakeTargetVerifier.VerifyTargetArgsForCall(0)).To(Equal("http://receptor.myapi.com"))
				Expect(fakeTargetVerifier.VerifyTargetArgsForCall(1)).To(Equal("http://*****:*****@receptor.myapi.com"))
					State:         "COMPLETED",
				},
				{
					TaskGuid:      "task-guid-3",
					CellID:        "",
					Failed:        true,
					FailureReason: "",
					Result:        "",
					State:         "COMPLETED",
				},
			}
			fakeTaskExaminer.ListTasksReturns(listTasks, nil)

			test_helpers.ExecuteCommandWithArgs(listAppsCommand, []string{})

			Expect(outputBuffer).To(test_helpers.Say(colors.Bold("App Name")))
			Expect(outputBuffer).To(test_helpers.Say(colors.Bold("Instances")))
			Expect(outputBuffer).To(test_helpers.Say(colors.Bold("DiskMB")))
			Expect(outputBuffer).To(test_helpers.Say(colors.Bold("MemoryMB")))
			Expect(outputBuffer).To(test_helpers.Say(colors.Bold("Route")))

			Expect(outputBuffer).To(test_helpers.Say(colors.Bold("process1")))
			Expect(outputBuffer).To(test_helpers.Say(colors.Red("0/21")))
			Expect(outputBuffer).To(test_helpers.Say(colors.NoColor("100")))
			Expect(outputBuffer).To(test_helpers.Say(colors.NoColor("50")))
			Expect(outputBuffer).To(test_helpers.Say("alldaylong.com => 54321"))

			Expect(outputBuffer).To(test_helpers.Say(colors.Bold("process2")))
			Expect(outputBuffer).To(test_helpers.Say(colors.Yellow("9/8")))
			Expect(outputBuffer).To(test_helpers.Say(colors.NoColor("400")))
			Expect(outputBuffer).To(test_helpers.Say(colors.NoColor("30")))
	"github.com/cloudfoundry-incubator/ltc/test_helpers"
)

var _ = Describe("RegexSafeSay", func() {
	var outputBuffer *gbytes.Buffer

	BeforeEach(func() {
		outputBuffer = gbytes.NewBuffer()
	})

	Describe("Say", func() {
		BeforeEach(func() {
			outputBuffer.Write([]byte(`match this \|?-^$.(){}`))
		})
		It("matches with regex-escaped characters", func() {
			Expect(outputBuffer).To(test_helpers.Say(`match this \|?-^$.(){}`))
		})
		It("negated match", func() {
			Expect(outputBuffer).NotTo(test_helpers.Say("match that"))
		})
		Context("when format string is passed with arguments", func() {
			It("matches with regex-escaped characters", func() {
				Expect(outputBuffer).To(test_helpers.Say(`match %s \|?-^$.(){}`, "this"))
			})
		})
	})

	Describe("SayLine", func() {
		BeforeEach(func() {
			outputBuffer.Write([]byte(`match this \|?-^$.(){}` + "\n"))
		})
				Expect(fakeDockerMetadataFetcher.FetchMetadataArgsForCall(0)).To(Equal("fun-org/app"))

				Expect(fakeAppRunner.CreateAppCallCount()).To(Equal(1))
				createAppParams := fakeAppRunner.CreateAppArgsForCall(0)
				Expect(createAppParams.StartCommand).To(Equal("/fetch-start"))
				Expect(createAppParams.AppArgs).To(Equal([]string{"arg1", "arg2"}))
				Expect(createAppParams.RootFS).To(Equal("docker:///fun-org/app#latest"))
				Expect(createAppParams.WorkingDir).To(Equal("/this/directory/right/here"))
			})

			It("does not output the working directory if it is not set", func() {
				fakeDockerMetadataFetcher.FetchMetadataReturns(&docker_metadata_fetcher.ImageMetadata{StartCommand: []string{"/fetch-start"}}, nil)

				test_helpers.ExecuteCommandWithArgs(createCommand, args)

				Expect(outputBuffer).NotTo(test_helpers.Say("Working directory is:"))
				Expect(fakeAppRunner.CreateAppCallCount()).To(Equal(1))
			})

			Context("when the metadata also has no start command", func() {
				It("outputs an error message and exits", func() {
					fakeDockerMetadataFetcher.FetchMetadataReturns(&docker_metadata_fetcher.ImageMetadata{}, nil)

					test_helpers.ExecuteCommandWithArgs(createCommand, args)

					Expect(outputBuffer).To(test_helpers.SayLine("Unable to determine start command from image metadata."))
					Expect(fakeAppRunner.CreateAppCallCount()).To(Equal(0))
					Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.BadDocker}))
				})
			})
		})