-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Get and GetCredentials for CFServiceInstances #3610
base: main
Are you sure you want to change the base?
Conversation
api/handlers/service_instance.go
Outdated
|
||
serviceInstance, err := h.serviceInstanceRepo.GetServiceInstance(r.Context(), authInfo, serviceInstanceGUID) | ||
if err != nil { | ||
return nil, apierrors.LogAndReturn(logger, err, "failed to get service instance") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should "mask" the forbidden error as "not found" in order not to leak information. See here for example
}) | ||
|
||
It("returns 404 Not Found", func() { | ||
expectNotAuthorizedError() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the It
says "returns 404" (correct), but it verifies for not authorised error (not correct :))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The api should mask forbidden error as not found. Therefore the test should expect a not found error rather then unauthorised. I think you did it the other way round :)
tools/credentials_test.go
Outdated
} | ||
}`), | ||
})) | ||
When("ToCredentialsSecretData", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This When
should be a Describe
as it describes a function under test
tools/credentials_test.go
Outdated
|
||
JustBeforeEach(func() { | ||
var err error | ||
secretData, err = tools.ToCredentialsSecretData(credsObject) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invoking the method under test should be performed within the describe for that function. It should not be invoked in the global describe
tools/credentials_test.go
Outdated
credsObject any | ||
secretData map[string][]byte | ||
credsObject any | ||
secretData map[string][]byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
secretData
can be local to the ToCredentialsSecretData
describe
tools/credentials_test.go
Outdated
secretData map[string][]byte | ||
credsObject any | ||
secretData map[string][]byte | ||
decodedCredentials map[string]any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decodedCredentials
should be pushed down to ToDecodedSecretDataCredentials
describe
Also, e2e tests would be nice for the two new endpoints |
@danail-branekov Did some changes, could you take a look. |
612645d
to
76ed317
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have resolved the comments that have been already addressed, and left the ones that have not been unresolved.
I have also added some more comments, please have a look
return nil, apierrors.LogAndReturn(logger, apierrors.ForbiddenAsNotFound(err), "failed to get service instance", "GUID", serviceInstanceGUID) | ||
} | ||
|
||
if serviceInstance.Type != korifiv1alpha1.UserProvidedType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to push this check to the repository (reasoning below). The repository looks up the service instance anyway, so it could return a not found error in case the service instance type is not upsi.
From API point of view, instance credentials are just another resource. We strive to keep api handlers simple and only take care to process the request parameters, delegate to a repository and present the result. Business logic on aspects of getting and processing resources should be "outsourced" to repositories.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forget about it, after a short discussion, having that decision in the handler is probably ok. Apologies for the noise
api/handlers/service_instance.go
Outdated
|
||
serviceInstance, err := h.serviceInstanceRepo.GetServiceInstance(r.Context(), authInfo, serviceInstanceGUID) | ||
if err != nil { | ||
return nil, apierrors.LogAndReturn(logger, err, "failed to get service instance") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still not resolved, the api should mask forbidden errors as not found
}) | ||
|
||
It("returns 404 Not Found", func() { | ||
expectNotAuthorizedError() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The api should mask forbidden error as not found. Therefore the test should expect a not found error rather then unauthorised. I think you did it the other way round :)
}) | ||
|
||
It("returns 404 Not Found", func() { | ||
_, actualAuthInfo, actualInstanceGUID := serviceInstanceRepo.GetServiceInstanceCredentialsArgsForCall(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my point of view, checking GetServiceInstanceCredentials
invocation and its parameter duplicates the checks in the default case. I think expecting a not found error is enough for this test.
}) | ||
}) | ||
|
||
When("getting the service instance fails with not found", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the handler should only interpret the "forbidden" error and present it as not found. Any other sort of errors (regiardless not found, general error, whatever) should be just returned.
Having said that, I would alter this When
to verify that when the repository returns a generic error, it results into an unexpected error (HTTP 500). In other words, as the handler does not handle the not found error in any particular way, I would go for the least specific test case.
}) | ||
}) | ||
|
||
When("the unmarshaling of the secret fails", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the comment on the "not found" error above. The handler does not handle unprocessable entity error in any particular way, it simply returns it. Another context with this particular error does not bring any more value. Therefore I would propose deleting at in order to keep the test simple
}) | ||
}) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a When
to verify that the repository returns unprocessiable entity error when the secret data is invalid json?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danail-branekov Maybe this is a stupid question, but how would I achieve that ? I would have to create a secret with an invalid json format, how would I marshal it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
secret = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: space.Name,
},
Data: map[string][]byte{korifiv1alpha1.CredentialSecretKey, []byte{"not-json"}},
}
Expect(k8sClient.Create(ctx, secret)).To(Succeed())
How about that?
Is there a related GitHub Issue?
#3609
#3608
What is this change about?
Here we expose GET /v3/service_instances/:guid and we also add GET /v3/service_instances/:guid/credentials
Does this PR introduce a breaking change?
No
Acceptance Steps
Tag your pair, your PM, and/or team