diff --git a/command/commandfakes/fake_ui.go b/command/commandfakes/fake_ui.go index 1e141f7bb8b..8dc9623340f 100644 --- a/command/commandfakes/fake_ui.go +++ b/command/commandfakes/fake_ui.go @@ -153,6 +153,11 @@ type FakeUI struct { arg1 string arg2 []map[string]interface{} } + DisplayTextLiteralStub func(string) + displayTextLiteralMutex sync.RWMutex + displayTextLiteralArgsForCall []struct { + arg1 string + } DisplayTextMenuStub func([]string, string, ...map[string]interface{}) (string, error) displayTextMenuMutex sync.RWMutex displayTextMenuArgsForCall []struct { @@ -1049,6 +1054,38 @@ func (fake *FakeUI) DisplayTextArgsForCall(i int) (string, []map[string]interfac return argsForCall.arg1, argsForCall.arg2 } +func (fake *FakeUI) DisplayTextLiteral(arg1 string) { + fake.displayTextLiteralMutex.Lock() + fake.displayTextLiteralArgsForCall = append(fake.displayTextLiteralArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.DisplayTextLiteralStub + fake.recordInvocation("DisplayTextLiteral", []interface{}{arg1}) + fake.displayTextLiteralMutex.Unlock() + if stub != nil { + fake.DisplayTextLiteralStub(arg1) + } +} + +func (fake *FakeUI) DisplayTextLiteralCallCount() int { + fake.displayTextLiteralMutex.RLock() + defer fake.displayTextLiteralMutex.RUnlock() + return len(fake.displayTextLiteralArgsForCall) +} + +func (fake *FakeUI) DisplayTextLiteralCalls(stub func(string)) { + fake.displayTextLiteralMutex.Lock() + defer fake.displayTextLiteralMutex.Unlock() + fake.DisplayTextLiteralStub = stub +} + +func (fake *FakeUI) DisplayTextLiteralArgsForCall(i int) string { + fake.displayTextLiteralMutex.RLock() + defer fake.displayTextLiteralMutex.RUnlock() + argsForCall := fake.displayTextLiteralArgsForCall[i] + return argsForCall.arg1 +} + func (fake *FakeUI) DisplayTextMenu(arg1 []string, arg2 string, arg3 ...map[string]interface{}) (string, error) { var arg1Copy []string if arg1 != nil { @@ -1802,6 +1839,8 @@ func (fake *FakeUI) Invocations() map[string][][]interface{} { defer fake.displayTableWithHeaderMutex.RUnlock() fake.displayTextMutex.RLock() defer fake.displayTextMutex.RUnlock() + fake.displayTextLiteralMutex.RLock() + defer fake.displayTextLiteralMutex.RUnlock() fake.displayTextMenuMutex.RLock() defer fake.displayTextMenuMutex.RUnlock() fake.displayTextPromptMutex.RLock() diff --git a/command/ui.go b/command/ui.go index 94ffab3244e..5059d6054da 100644 --- a/command/ui.go +++ b/command/ui.go @@ -30,6 +30,7 @@ type UI interface { DisplayPasswordPrompt(template string, templateValues ...map[string]interface{}) (string, error) DisplayTableWithHeader(prefix string, table [][]string, padding int) DisplayText(template string, data ...map[string]interface{}) + DisplayTextLiteral(text string) DisplayTextMenu(choices []string, promptTemplate string, templateValues ...map[string]interface{}) (string, error) DisplayTextPrompt(template string, templateValues ...map[string]interface{}) (string, error) DisplayTextWithBold(text string, keys ...map[string]interface{}) diff --git a/command/v7/env_command.go b/command/v7/env_command.go index 84b05fdb8b8..6896356ee04 100644 --- a/command/v7/env_command.go +++ b/command/v7/env_command.go @@ -93,7 +93,7 @@ func (cmd EnvCommand) displayEnvGroup(group map[string]interface{}) { keys := sortKeys(group) for _, key := range keys { - cmd.UI.DisplayText(fmt.Sprintf("%s: %v", key, group[key])) + cmd.UI.DisplayTextLiteral(fmt.Sprintf("%s: %v", key, group[key])) } } diff --git a/command/v7/env_command_test.go b/command/v7/env_command_test.go index fcf4088f90a..d80bd94844c 100644 --- a/command/v7/env_command_test.go +++ b/command/v7/env_command_test.go @@ -232,6 +232,42 @@ var _ = Describe("env Command", func() { Expect(testUI.Err).To(Say("get-warning-2")) }) }) + + When("getting the environment returns env vars with special templating characters", func() { + BeforeEach(func() { + envGroups := v7action.EnvironmentVariableGroups{ + System: map[string]interface{}{"system-name": map[string]interface{}{"mysql": []string{"system-value"}, "password": "{{test<3"}}, + Application: map[string]interface{}{"application-name": "{{application-value"}, + EnvironmentVariables: map[string]interface{}{"user-name": "{{user-value"}, + Running: map[string]interface{}{"running-name": "{{running-value"}, + Staging: map[string]interface{}{"staging-name": "{{staging-value"}, + } + fakeActor.GetEnvironmentVariablesByApplicationNameAndSpaceReturns(envGroups, nil, nil) + }) + + It("displays the environment variable and value pair", func() { + Expect(executeErr).ToNot(HaveOccurred()) + + Expect(testUI.Out).To(Say(`Getting env variables for app some-app in org some-org / space some-space as banana\.\.\.`)) + Expect(testUI.Out).To(Say("System-Provided:")) + Expect(testUI.Out).To(Say("system-name: {")) + Expect(testUI.Out).To(Say(`"mysql": \[`)) + Expect(testUI.Out).To(Say(`"system-value"`)) + Expect(testUI.Out).To(Say(`\],`)) + Expect(testUI.Out).To(Say(`"password": "{{test<3"`)) + Expect(testUI.Out).To(Say("}")) + Expect(testUI.Out).To(Say(`application-name: "{{application-value"`)) + + Expect(testUI.Out).To(Say("User-Provided:")) + Expect(testUI.Out).To(Say(`user-name: {{user-value`)) + + Expect(testUI.Out).To(Say("Running Environment Variable Groups:")) + Expect(testUI.Out).To(Say(`running-name: {{running-value`)) + + Expect(testUI.Out).To(Say("Staging Environment Variable Groups:")) + Expect(testUI.Out).To(Say(`staging-name: {{staging-value`)) + }) + }) }) }) }) diff --git a/util/ui/ui.go b/util/ui/ui.go index 625a72ef56d..b4d7cd7b383 100644 --- a/util/ui/ui.go +++ b/util/ui/ui.go @@ -248,6 +248,15 @@ func (ui *UI) DisplayText(template string, templateValues ...map[string]interfac fmt.Fprintf(ui.Out, "%s\n", ui.TranslateText(template, templateValues...)) } +// DisplayTextLiteral outputs the text to ui.Out without modification. +// This function should only be used when no translation or templating is required. +func (ui *UI) DisplayTextLiteral(text string) { + ui.terminalLock.Lock() + defer ui.terminalLock.Unlock() + + fmt.Fprintf(ui.Out, "%s\n", text) +} + // DisplayTextWithBold translates the template, bolds the templateValues, // substitutes templateValues into the template, and outputs // the result to ui.Out. Only the first map in templateValues is used. diff --git a/util/ui/ui_test.go b/util/ui/ui_test.go index 91882e8827c..da63a0449d0 100644 --- a/util/ui/ui_test.go +++ b/util/ui/ui_test.go @@ -186,6 +186,13 @@ var _ = Describe("UI", func() { }) }) + Describe("DisplayTextLiteral", func() { + It("displays the text into ui.Out with a newline", func() { + ui.DisplayTextLiteral("some text") + Expect(out).To(Say("some text\n")) + }) + }) + Describe("Display JSON", func() { It("displays the indented JSON object", func() { obj := map[string]interface{}{