func MakeCliApp(
	diegoVersion string,
	latticeVersion string,
	ltcConfigRoot string,
	exitHandler exit_handler.ExitHandler,
	config *config.Config,
	logger lager.Logger,
	receptorClientCreator receptor_client.Creator,
	targetVerifier target_verifier.TargetVerifier,
	cliStdout io.Writer,
) *cli.App {
	config.Load()
	app := cli.NewApp()
	app.Name = AppName
	app.Author = latticeCliAuthor
	app.Version = defaultVersion(diegoVersion, latticeVersion)
	app.Usage = LtcUsage
	app.Email = "*****@*****.**"

	ui := terminal.NewUI(os.Stdin, cliStdout, terminal.NewPasswordReader())
	app.Writer = ui

	app.Before = func(context *cli.Context) error {
		args := context.Args()
		command := app.Command(args.First())

		if command == nil {
			return nil
		}

		if _, ok := nonTargetVerifiedCommandNames[command.Name]; ok || len(args) == 0 {
			return nil
		}

		for _, arg := range args {
			if arg == "-h" || arg == "--help" {
				return nil
			}
		}

		if receptorUp, authorized, err := targetVerifier.VerifyTarget(config.Receptor()); !receptorUp {
			ui.SayLine(fmt.Sprintf("Error connecting to the receptor. Make sure your lattice target is set, and that lattice is up and running.\n\tUnderlying error: %s", err))
			return err
		} else if !authorized {
			ui.SayLine("Could not authenticate with the receptor. Please run ltc target with the correct credentials.")
			return errors.New("Could not authenticate with the receptor.")
		}
		return nil
	}

	app.Action = defaultAction
	app.CommandNotFound = func(c *cli.Context, command string) {
		ui.SayLine(fmt.Sprintf(unknownCommand, command))
		exitHandler.Exit(1)
	}
	app.Commands = cliCommands(ltcConfigRoot, exitHandler, config, logger, receptorClientCreator, targetVerifier, ui, latticeVersion)
	return app
}
		consoleTailedLogsOutputter *console_tailed_logs_outputter.ConsoleTailedLogsOutputter
	)

	buildLogMessage := func(sourceType, sourceInstance string, timestamp time.Time, message []byte) *events.LogMessage {
		unixTime := timestamp.UnixNano()
		return &events.LogMessage{
			Message:        message,
			Timestamp:      &unixTime,
			SourceType:     &sourceType,
			SourceInstance: &sourceInstance,
		}
	}

	BeforeEach(func() {
		outputBuffer = gbytes.NewBuffer()
		terminalUI = terminal.NewUI(nil, outputBuffer, nil)
		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"))
)

var _ = Describe("UI", func() {
	var (
		stdinReader        *io.PipeReader
		stdinWriter        *io.PipeWriter
		outputBuffer       *gbytes.Buffer
		fakePasswordReader *mocks.FakePasswordReader
		terminalUI         terminal.UI
	)

	BeforeEach(func() {
		stdinReader, stdinWriter = io.Pipe()
		outputBuffer = gbytes.NewBuffer()
		fakePasswordReader = &mocks.FakePasswordReader{}
		terminalUI = terminal.NewUI(stdinReader, outputBuffer, fakePasswordReader)
	})

	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")
		fakeDropletRunner = &fake_droplet_runner.FakeDropletRunner{}
		fakeExitHandler = &fake_exit_handler.FakeExitHandler{}
		fakeTailedLogsOutputter = fake_tailed_logs_outputter.NewFakeTailedLogsOutputter()
		fakeClock = fakeclock.NewFakeClock(time.Now())
		fakeAppExaminer = &fake_app_examiner.FakeAppExaminer{}
		fakeTaskExaminer = &fake_task_examiner.FakeTaskExaminer{}
		fakeCFIgnore = &fake_cf_ignore.FakeCFIgnore{}
		fakeZipper = &fake_zipper.FakeZipper{}
		fakeBlobStoreVerifier = &fake_blob_store_verifier.FakeBlobStoreVerifier{}
		config = config_package.New(nil)

		outputBuffer = gbytes.NewBuffer()
		appRunnerCommandFactory = app_runner_command_factory.AppRunnerCommandFactory{
			AppRunner:           &fake_app_runner.FakeAppRunner{},
			AppExaminer:         fakeAppExaminer,
			UI:                  terminal.NewUI(nil, outputBuffer, nil),
			ExitHandler:         fakeExitHandler,
			TailedLogsOutputter: fakeTailedLogsOutputter,
			Clock:               fakeClock,
			Domain:              "192.168.11.11.xip.io",
			Env:                 []string{"SHELL=/bin/bash", "COLOR=Black", "AAAA=xyz"},
		}
	})

	Describe("BuildDropletCommand", func() {
		var buildDropletCommand cli.Command

		BeforeEach(func() {
			commandFactory := droplet_runner_command_factory.NewDropletRunnerCommandFactory(appRunnerCommandFactory, fakeBlobStoreVerifier, fakeTaskExaminer, fakeDropletRunner, fakeCFIgnore, fakeZipper, config)
			buildDropletCommand = commandFactory.MakeBuildDropletCommand()
			fakeBlobStoreVerifier.VerifyReturns(true, nil)