Skip to content

Commit 8494540

Browse files
authored
[Bugfix] Idempotency when trying to share a service twice (#2875)
1 parent b74ae37 commit 8494540

File tree

5 files changed

+62
-1
lines changed

5 files changed

+62
-1
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package ccerror
2+
3+
// ServiceInstanceAlreadySharedError is returned when a
4+
// service instance is already shared.
5+
type ServiceInstanceAlreadySharedError struct {
6+
Message string
7+
}
8+
9+
func (e ServiceInstanceAlreadySharedError) Error() string {
10+
return e.Message
11+
}

api/cloudcontroller/ccv3/errors.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func handleUnprocessableEntity(errorResponse ccerror.V3Error) error {
154154
roleExistsRegexp := regexp.MustCompile(`User '.*' already has '.*' role.*`)
155155
quotaExistsRegexp := regexp.MustCompile(`.* Quota '.*' already exists\.`)
156156
securityGroupExistsRegexp := regexp.MustCompile(`Security group with name '.*' already exists\.`)
157+
serviceInstanceSharedRegexp := regexp.MustCompile(`A service instance called .* has already been shared with .*\.`)
157158

158159
// boolean switch case with partial/regex string matchers
159160
switch {
@@ -174,6 +175,8 @@ func handleUnprocessableEntity(errorResponse ccerror.V3Error) error {
174175
case strings.Contains(errorString,
175176
"The service instance name is taken"):
176177
return ccerror.ServiceInstanceNameTakenError{Message: err.Message}
178+
case serviceInstanceSharedRegexp.MatchString(errorString):
179+
return ccerror.ServiceInstanceAlreadySharedError{Message: err.Message}
177180
case orgNameTakenRegexp.MatchString(errorString):
178181
return ccerror.OrganizationNameTakenError{UnprocessableEntityError: err}
179182
case roleExistsRegexp.MatchString(errorString):

api/cloudcontroller/ccv3/errors_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,27 @@ var _ = Describe("Error Wrapper", func() {
507507
})
508508
})
509509

510+
When("the service instance has already been shared", func() {
511+
BeforeEach(func() {
512+
serverResponse = `
513+
{
514+
"errors": [
515+
{
516+
"code": 10008,
517+
"detail": "A service instance called foo has already been shared with foo-space.",
518+
"title": "CF-UnprocessableEntity"
519+
}
520+
]
521+
}`
522+
})
523+
524+
It("returns an ServiceInstanceAlreadySharedError", func() {
525+
Expect(makeError).To(MatchError(ccerror.ServiceInstanceAlreadySharedError{
526+
Message: "A service instance called foo has already been shared with foo-space.",
527+
}))
528+
})
529+
})
530+
510531
When("the buildpack is invalid", func() {
511532
BeforeEach(func() {
512533
serverResponse = `

command/v7/share_service_command.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package v7
22

33
import (
44
"code.cloudfoundry.org/cli/actor/v7action"
5+
"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
56
"code.cloudfoundry.org/cli/command/flag"
67
"code.cloudfoundry.org/cli/types"
78
)
@@ -38,7 +39,14 @@ func (cmd ShareServiceCommand) Execute(args []string) error {
3839
})
3940

4041
cmd.UI.DisplayWarnings(warnings)
41-
if err != nil {
42+
43+
switch err.(type) {
44+
case nil:
45+
case ccerror.ServiceInstanceAlreadySharedError:
46+
cmd.UI.DisplayOK()
47+
cmd.UI.DisplayTextWithFlavor("A service instance called {{.ServiceInstanceName}} has already been shared", map[string]interface{}{"ServiceInstanceName": cmd.RequiredArgs.ServiceInstance})
48+
return nil
49+
default:
4250
return err
4351
}
4452

command/v7/share_service_command_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package v7_test
33
import (
44
"errors"
55

6+
"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
67
"code.cloudfoundry.org/cli/util/configv3"
78

89
"code.cloudfoundry.org/cli/command/flag"
@@ -141,6 +142,23 @@ var _ = Describe("share-service command", func() {
141142
})
142143
})
143144

145+
When("the service instance is already shared", func() {
146+
BeforeEach(func() {
147+
fakeActor.ShareServiceInstanceToSpaceAndOrgReturns(v7action.Warnings{"warning one", "warning two"}, ccerror.ServiceInstanceAlreadySharedError{})
148+
})
149+
150+
It("succeeds, displaying warnings, 'OK' and an informative message", func() {
151+
Expect(executeErr).NotTo(HaveOccurred())
152+
153+
Expect(testUI.Out).To(Say(`OK`))
154+
Expect(testUI.Err).To(SatisfyAll(
155+
Say("warning one"),
156+
Say("warning two"),
157+
))
158+
Expect(testUI.Out).To(Say("A service instance called %s has already been shared", expectedServiceInstanceName))
159+
})
160+
})
161+
144162
When("the actor errors", func() {
145163
BeforeEach(func() {
146164
fakeSharedActor.CheckTargetReturns(nil)

0 commit comments

Comments
 (0)