Skip to content

Commit 0d33a88

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 0d33a88

File tree

2 files changed

+83
-13
lines changed

2 files changed

+83
-13
lines changed

command/v7/service_key_command.go

Lines changed: 24 additions & 13 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
}
@@ -38,14 +41,27 @@ func (cmd ServiceKeyCommand) guid() error {
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:
44+
if err != nil {
4645
cmd.UI.DisplayWarnings(warnings)
4746
return err
4847
}
48+
49+
cmd.UI.DisplayText(key.GUID)
50+
return nil
51+
}
52+
53+
func (cmd ServiceKeyCommand) json() error {
54+
details, warnings, err := cmd.Actor.GetServiceKeyDetailsByServiceInstanceAndName(
55+
cmd.RequiredArgs.ServiceInstance,
56+
cmd.RequiredArgs.ServiceKey,
57+
cmd.Config.TargetedSpace().GUID,
58+
)
59+
if err != nil {
60+
cmd.UI.DisplayWarnings(warnings)
61+
return err
62+
}
63+
64+
return cmd.UI.DisplayJSON("", details)
4965
}
5066

5167
func (cmd ServiceKeyCommand) details() error {
@@ -72,10 +88,5 @@ func (cmd ServiceKeyCommand) details() error {
7288

7389
cmd.UI.DisplayNewline()
7490

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

command/v7/service_key_command_test.go

Lines changed: 59 additions & 0 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

@@ -167,4 +177,53 @@ var _ = Describe("service-key Command", func() {
167177
})
168178
})
169179
})
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("prints warnings and returns an error", func() {
224+
Expect(testUI.Err).To(Say("a warning"))
225+
Expect(executeErr).To(MatchError("bang"))
226+
})
227+
})
228+
})
170229
})

0 commit comments

Comments
 (0)