Skip to content

Commit 5d3bad9

Browse files
committed
feat: add --json flag to "service-key" subcommand
It's very common to see code like: ``` cf service-key "$SERVICE_INSTANCE_NAME" $KEY_NAME | tail -n +2 ``` This removed the header from the output leaving just JSON. Search GitHub and you'll see pages of hits. Rather than forcing script users to chop of the header, risking issues with errors in pipes, etc... It woudld be better just to print the correct output in the first place. This commit: adds a "--json" flag which outputs JSON only. It follows the convention of "--guid" to supress warnings too (unless there an error). In practice the endpoints in question do not produce warnings, so it makes no practical difference.
1 parent 9bbfed8 commit 5d3bad9

File tree

2 files changed

+85
-17
lines changed

2 files changed

+85
-17
lines changed

command/v7/service_key_command.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@ type ServiceKeyCommand struct {
99

1010
RequiredArgs flag.ServiceInstanceKey `positional-args:"yes"`
1111
GUID bool `long:"guid" description:"Retrieve and display the given service-key's guid. All other output is suppressed."`
12+
JSON bool `long:"json" description:"Output credentials as JSON. All other output is suppressed."`
1213
}
1314

1415
func (cmd ServiceKeyCommand) Execute(args []string) error {
1516
if err := cmd.SharedActor.CheckTarget(true, true); err != nil {
1617
return err
1718
}
1819

19-
switch cmd.GUID {
20-
case true:
20+
switch {
21+
case cmd.GUID:
2122
return cmd.guid()
23+
case cmd.JSON:
24+
return cmd.json()
2225
default:
2326
return cmd.details()
2427
}
@@ -33,19 +36,30 @@ func (cmd ServiceKeyCommand) Examples() string {
3336
}
3437

3538
func (cmd ServiceKeyCommand) guid() error {
36-
key, warnings, err := cmd.Actor.GetServiceKeyByServiceInstanceAndName(
39+
key, _, err := cmd.Actor.GetServiceKeyByServiceInstanceAndName(
3740
cmd.RequiredArgs.ServiceInstance,
3841
cmd.RequiredArgs.ServiceKey,
3942
cmd.Config.TargetedSpace().GUID,
4043
)
41-
switch err.(type) {
42-
case nil:
43-
cmd.UI.DisplayText(key.GUID)
44-
return nil
45-
default:
46-
cmd.UI.DisplayWarnings(warnings)
44+
if err != nil {
4745
return err
4846
}
47+
48+
cmd.UI.DisplayText(key.GUID)
49+
return nil
50+
}
51+
52+
func (cmd ServiceKeyCommand) json() error {
53+
details, _, err := cmd.Actor.GetServiceKeyDetailsByServiceInstanceAndName(
54+
cmd.RequiredArgs.ServiceInstance,
55+
cmd.RequiredArgs.ServiceKey,
56+
cmd.Config.TargetedSpace().GUID,
57+
)
58+
if err != nil {
59+
return err
60+
}
61+
62+
return cmd.UI.DisplayJSON("", details)
4963
}
5064

5165
func (cmd ServiceKeyCommand) details() error {
@@ -72,10 +86,5 @@ func (cmd ServiceKeyCommand) details() error {
7286

7387
cmd.UI.DisplayNewline()
7488

75-
err = cmd.UI.DisplayJSON("", details)
76-
if err != nil {
77-
return err
78-
}
79-
80-
return nil
89+
return cmd.UI.DisplayJSON("", details)
8190
}

command/v7/service_key_command_test.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ var _ = Describe("service-key Command", func() {
6464
Expect(actualSpace).To(BeTrue())
6565
})
6666

67+
When("checking target fails", func() {
68+
BeforeEach(func() {
69+
fakeSharedActor.CheckTargetReturns(errors.New("not logged in"))
70+
})
71+
72+
It("returns the error", func() {
73+
Expect(executeErr).To(MatchError("not logged in"))
74+
})
75+
})
76+
6777
When("getting details", func() {
6878
const fakeUserName = "fake-user-name"
6979

@@ -161,8 +171,57 @@ var _ = Describe("service-key Command", func() {
161171
)
162172
})
163173

164-
It("prints warnings and returns an error", func() {
165-
Expect(testUI.Err).To(Say("a warning"))
174+
It("returns an error without warnings", func() {
175+
Expect(testUI.Err).NotTo(Say("a warning"))
176+
Expect(executeErr).To(MatchError("bang"))
177+
})
178+
})
179+
})
180+
181+
When("getting JSON output", func() {
182+
BeforeEach(func() {
183+
fakeActor.GetServiceKeyDetailsByServiceInstanceAndNameReturns(
184+
resources.ServiceCredentialBindingDetails{
185+
Credentials: map[string]interface{}{"foo": "bar", "pass": "<3test"},
186+
},
187+
v7action.Warnings{"a warning"},
188+
nil,
189+
)
190+
191+
setFlag(&cmd, "--json")
192+
})
193+
194+
It("delegates to the actor", func() {
195+
Expect(fakeActor.GetServiceKeyDetailsByServiceInstanceAndNameCallCount()).To(Equal(1))
196+
actualServiceInstanceName, actualKeyName, actualSpaceGUID := fakeActor.GetServiceKeyDetailsByServiceInstanceAndNameArgsForCall(0)
197+
Expect(actualServiceInstanceName).To(Equal(fakeServiceInstanceName))
198+
Expect(actualKeyName).To(Equal(fakeServiceKeyName))
199+
Expect(actualSpaceGUID).To(Equal(fakeSpaceGUID))
200+
})
201+
202+
It("prints JSON without intro message or warnings", func() {
203+
Expect(executeErr).NotTo(HaveOccurred())
204+
Expect(testUI.Err).NotTo(Say("a warning"))
205+
Expect(testUI.Out).NotTo(Say("Getting key"))
206+
Expect(testUI.Out).To(SatisfyAll(
207+
Say(`\{\n`),
208+
Say(` "foo": "bar",\n`),
209+
Say(` "pass": "<3test"\n`),
210+
Say(`\}\n`),
211+
))
212+
})
213+
214+
When("actor returns an error", func() {
215+
BeforeEach(func() {
216+
fakeActor.GetServiceKeyDetailsByServiceInstanceAndNameReturns(
217+
resources.ServiceCredentialBindingDetails{},
218+
v7action.Warnings{"a warning"},
219+
errors.New("bang"),
220+
)
221+
})
222+
223+
It("returns an error without warnings", func() {
224+
Expect(testUI.Err).NotTo(Say("a warning"))
166225
Expect(executeErr).To(MatchError("bang"))
167226
})
168227
})

0 commit comments

Comments
 (0)