-
Notifications
You must be signed in to change notification settings - Fork 706
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
Avoid to submit empty params #735
Conversation
}, | ||
}, | ||
}; | ||
// It omits "f" because it's empty but not "b" because it's required |
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.
Thanks for explanation.
What's the difference between sending empty required parameters and not sending them at all? Wouldn't not sending the empty parameters regardless of being required or not have the same effect?
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.
Nope, that't the root of the issue of #411. The GCP service broker has some kind of validation that if the key exists it's not empty. We were sending a subscription
object with all the inner elements empty (but with keys). With that the broker replies 'roles/pubsub.subscriber' is a required role when 'subscription' is specified
.
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.
right, my comment was related to not to send the parameters if they are empty in any case. The difference is that you still send them if they are required params but I am suggesting not to send them even in that case. I might be missing something though.
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.
okay, yes, it's true that it should be safe to not send anything that is empty.
dashboard/src/actions/catalog.ts
Outdated
@@ -60,16 +62,44 @@ const actions = [ | |||
|
|||
export type ServiceCatalogAction = ActionType<typeof actions[number]>; | |||
|
|||
function isEmptyDeep(obj: any): boolean { |
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.
Please add a description of what this function does. Mainly because it seems to have a recursive behavior.
dashboard/src/actions/catalog.ts
Outdated
@@ -60,16 +62,44 @@ const actions = [ | |||
|
|||
export type ServiceCatalogAction = ActionType<typeof actions[number]>; | |||
|
|||
function isEmptyDeep(obj: any): boolean { | |||
if (typeof obj === "number") { |
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.
why is number a special case? What about string and others?
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.
it's a lodash
problem:
In our case, we want to mark a number as non empty so we need this special case. It's not critical though because you cannot set a "number" in a form (AFAIK) but just in case.
dashboard/src/actions/catalog.ts
Outdated
return _.isEmpty(obj); | ||
} | ||
|
||
function removeEmptyFields(obj: object, schema?: JSONSchema6) { |
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.
maybe rename to removeEmptyNonRequiredFields
?
dashboard/src/actions/catalog.ts
Outdated
@@ -60,16 +62,44 @@ const actions = [ | |||
|
|||
export type ServiceCatalogAction = ActionType<typeof actions[number]>; | |||
|
|||
function isEmptyDeep(obj: any): boolean { |
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 know that we are testing the overall behavior at the action level but could we add unit tests for this function?
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 would avoid that because that would require to export the function. This is supposed to be a inner function so I prefer to test this with the exposed function.
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 don't know. There should be a way to unit test functions without exporting them, otherwise we are not unit testing.
Can't we make it work like this?
wrapper = shallow("foo")
instance = wrapper.instance();
instance.isEmptyDeep(...) ?
The thing is that this function is complex enough too deserve its unit test. Relying on functional/integration test might not be the best option once the complexity starts growing.
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.
moving this function to a different helper to be able to test it
dashboard/src/actions/catalog.ts
Outdated
): ThunkAction<Promise<boolean>, IStoreState, null, ServiceCatalogAction> { | ||
return async dispatch => { | ||
try { | ||
await ServiceInstance.create(releaseName, namespace, className, planName, parameters); | ||
const filteredParams = removeEmptyFields(parameters, schema); |
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.
maybe we do not need to pass schema all the time since it is actually optional and with default value to JSONSchema6
? Or do we support other schemas?
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 don't understand what you mean here
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.
My bad, I was understanding schema like the schema type and thought that the default value was JSONSchema6
. When what it actually does it to receive an instance of jsonschema.
dashboard/src/actions/catalog.ts
Outdated
export function provision( | ||
releaseName: string, | ||
namespace: string, | ||
className: string, | ||
planName: string, | ||
parameters: {}, | ||
schema?: JSONSchema6, |
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.
Why is schema optional?
}, | ||
}, | ||
}; | ||
// It omits "f" because it's empty but not "b" because it's required |
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.
right, my comment was related to not to send the parameters if they are empty in any case. The difference is that you still send them if they are required params but I am suggesting not to send them even in that case. I might be missing something though.
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 great, thanks for the changes :)
@@ -165,6 +165,40 @@ describe("provision", () => { | |||
await store.dispatch(provisionCMD); | |||
expect(store.getActions()).toEqual(expectedActions); | |||
}); | |||
|
|||
it("filters the submitted parameters if they are not required", async () => { |
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.
Is that description accurate?
filters submitted params if they are empty?
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.
it's not, I missed this
@@ -227,6 +261,41 @@ describe("addBinding", () => { | |||
await store.dispatch(provisionCMD); | |||
expect(store.getActions()).toEqual(expectedActions); | |||
}); | |||
|
|||
it("filters the submitted parameters if they are not required", async () => { |
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.
same here
@@ -69,7 +70,8 @@ export function provision( | |||
): ThunkAction<Promise<boolean>, IStoreState, null, ServiceCatalogAction> { | |||
return async dispatch => { | |||
try { | |||
await ServiceInstance.create(releaseName, namespace, className, planName, parameters); | |||
const filteredParams = helpers.object.removeEmptyFields(parameters); |
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.
nice.
@@ -0,0 +1,34 @@ | |||
import * as object from "./object"; | |||
|
|||
describe("isEmptyDeep", () => { |
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.
great :)
{ object: { a: 1 }, isEmpty: false }, | ||
{ object: { a: { b: "" } }, isEmpty: true }, | ||
{ object: { a: { c: { d: "" } } }, isEmpty: true }, | ||
{ object: { a: { c: { d: "a" } } }, isEmpty: false }, |
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.
what about an example that contains both an empty and non-empty at the leaf?
{ object: { a: { c: { d: "a" }, d: "" } }, isEmpty: false },
@@ -0,0 +1,30 @@ | |||
import * as _ from "lodash"; | |||
|
|||
// Check if all the keys of an object are empty. If any value of the |
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.
Thank you for the description :)
// is empty. | ||
export function isEmptyDeep(obj: any): boolean { | ||
if (typeof obj === "number") { | ||
// isEmpty(number) is true but it's not empty |
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 mention that it is a limitation of lodash?
Fixes #411
When creating a service instance or a binding, if the schema is provided, avoid to submit empty objects. This is only made when we are sure that the parameter is not required.