Skip to content
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

feat(cdevents-webhooks) : Consume CDEvents webhook API implementation #1651

Merged
merged 29 commits into from
Aug 14, 2023

Conversation

rjalander
Copy link
Contributor

@rjalander rjalander commented Apr 11, 2023

Changes to implement a new CDEvents webhook API /webhooks/cdevents/{source} end point to Consume CDEvent

Note:
The implementation is as per the RFC design
https://github.com/spinnaker/governance/blob/master/rfc/cdevents-spinnaker.md#implementation-details

Dependent Spinnaker/deck PR - spinnaker/deck#9977
Dependent Spinnaker/echo PR - spinnaker/echo#1290

@spinnakerbot
Copy link
Contributor

The following commits need their title changed:

Please format your commit title into the form:

<type>(<scope>): <subject>, e.g. fix(kubernetes): address NPE in status check

This allows us to easily generate changelogs & determine semantic version numbers when cutting releases. You can read more about commit conventions here.

@mattgogerly
Copy link
Member

@Mergifyio update

@mergify
Copy link
Contributor

mergify bot commented Jun 16, 2023

update

❌ Pull request can't be updated with latest base branch changes

Mergify needs the author permission to update the base branch of the pull request.
@Nordix needs to authorize modification on its head branch.
err-code: 427B6

@rjalander
Copy link
Contributor Author

Thank you for checking this PR @mattgogerly, I have updated the base branch now.

@mattgogerly
Copy link
Member

Thanks, sorry it's taken so long to get this reviewed. I'm double checking with the TOC and if there's no objections I'll get these merged.

@@ -340,6 +342,7 @@ class GateConfig extends RedisHttpSessionConfiguration {
.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.registerModule(new JavaTimeModule())
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate on why these changes are necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah with out setting this, when sending CDEvent POST request to this webhook will result in below error in the response;

{"error":"Internal Server Error","exception":"retrofit.RetrofitError","message":"com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class io.cloudevents.core.data.BytesCloudEventData and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: io.cloudevents.core.v1.CloudEventV1[\"data\"])"}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I'd like to get @link108 or @dbyron-sf's thoughts on this. I'm hesitant to change this for the global ObjectMapper without thorough understanding of any side effects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setting is what I need it for echoservice.
If this is fine, I can only set it for echo as below also works for me

Suggested change
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
if(serviceName.equals("echo")){
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
}
  

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@link108 @dbyron-sf any suggestion on this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the master branch changes which is conflicting with this change, now objectMapper is configured using Jackson2ObjectMapperBuilder,
But still the property spring.jackson.serialization.fail-on-empty-beans=false needs to be added in gate-web/src/main/resources/application.properties as per the master branch change. Please share your thoughts on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super familiar with the consequences of setting fail-on-empty-beans to false. Maybe @jvz knows?

What would it take with the latest code on master to configure it that way only for echo?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really sure myself what that does. I learn something new about Jackson every time I use it, though! If the setting isn't safe to set globally, then what you can do is update the EchoService bean to use the objectMapperBuilder field to create a custom ObjectMapper as that bean is prototype-scoped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the same way, setting this configuration only for echo as suggested above with in the buildService method

gate-web/gate-web.gradle Outdated Show resolved Hide resolved
gate-core/gate-core.gradle Outdated Show resolved Hide resolved
@rjalander rjalander requested review from dbyron-sf and jvz July 10, 2023 15:39

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new CloudEventHttpMessageConverter());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this would set the default message converter for all of Gate's controllers, wouldn't it? Or is this a different MIME type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a different type, this will help to write an endpoints with CloudEvent input or output,
More information here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is the content-type or accept HTTP headers. If this is just application/json, then it will override the converter used for every other request in gate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this configuration will add to the list of existing converters but not override or replace the configuration.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It adds it to the front of the list, though! If you can add it without an index, then that should work, though then you could just define a bean of CloudEventHttpMessageConverter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this converter without index is causing an issue with InvalidDefinitionException,
So keeping index at 0 and defined a bean of CloudEventHttpMessageConverter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting it at index 0 means making it top priority. That is causing it to be used instead of the JSON message converter you were updating before making the custom one. It might just be simpler to update the properties file like you did previously if this setting is required globally. Alternatively, I'd suggest looking at Jackson's annotations and mixins for a potentially localized solution here, but perhaps that's unnecessary. While Jackson provides numerous knobs for tuning things, it's kind of complicated in my experience.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes in this case its working only when keeping this converter at index 0.

Updating properties file is actually for objectMapper configuration(SerializationFeature.FAIL_ON_EMPTY_BEANS) and not for CloudEventHttpMessageConverter If I am not wrong.

Yeah I don't see any Jackson's annotations to set the localized configuration at a request level for adding converters like CloudEventHttpMessageConverter but it is possible when we use rest client for any requests something like below,
restTemplate.getMessageConverters().add(0, new CloudEventHttpMessageConverter());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay in response.
I have re-tested this, it works perfectly fine when keeping the CloudEventHandlerConfiguration.java under gate-web project instead of gate-core with out indexing at top priority.(not sure why it's working other way when index set to 0)


@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new CloudEventHttpMessageConverter());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this twice seems redundant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we have different endpoints written in gate-core and gate-web separately, we need this configuration to handle the CloudEvent conversion by Spring framework.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure that beans defined in core also show up in web regardless if it's an api or implementation dependency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes apologies, it works keeping this config file in either core or web. I will delete this config file from web

@rjalander rjalander requested a review from jvz July 13, 2023 08:59
@rjalander
Copy link
Contributor Author

@mattgogerly @jvz @dbyron-sf Thank you all for reviewing this PR, please let me know If you have any other comments.
Thank you

Copy link
Contributor

@jvz jvz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for dealing with the Jackson madness! I'm alright with the changes now.

@rjalander
Copy link
Contributor Author

Thanks @jvz.
@mattgogerly @dbyron-sf can you approve/merge this PR If no other comments.

@mattgogerly mattgogerly added the ready to merge Approved and ready for merge label Aug 11, 2023
@mergify mergify bot added the auto merged label Aug 11, 2023
@mergify mergify bot merged commit f57df15 into spinnaker:master Aug 14, 2023
4 checks passed
@rjalander
Copy link
Contributor Author

@mattgogerly in the same context I have created PRs for producing CDEvents using Notifications,
spinnaker/deck#9997
spinnaker/echo#1295
Please add reviewers to the above PRs and help in reviewing. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants