-
Notifications
You must be signed in to change notification settings - Fork 29
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
Define CAMARA Event using cloudevents in OAS notification #43
Changes from 9 commits
3dd803c
8a11ac5
339a8e2
e2418d3
0c6c11f
a97bb67
9226178
234cfdb
8922567
950efcd
7904ec2
fd986cd
2420cf3
2eb7b7d
b7eb630
248e442
14b8650
441360c
21711ac
e90cdd7
338a4a2
3b19bae
fec372a
430f4ca
984794b
2d4683a
e5ced0d
429a7e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
openapi: 3.0.3 | ||
info: | ||
title: Event Notification using CloudEvents specifications | ||
description: | | ||
The event notification endpoint is used by the API server to notify the API consumer that an event occurred. The notification is the message posted on listener side. | ||
|
||
# Introduction | ||
|
||
A lot of CAMARA APIs offer the capability to API consumer to receive events. | ||
Event data are defined in each API definition but in order to provide consistency across CAMARA APIs and to increase | ||
interoperability we will use [cloudevents](https://cloudevents.io/) specifications. In particular, every CAMARA Event will | ||
be defined using [cloudevents-json-format](https://github.com/cloudevents/spec/blob/main/cloudevents/formats/json-format.md) | ||
|
||
# Relevant terms and definitions | ||
|
||
* **Occurrence** : An "occurrence" is the capture of a statement of fact during the operation of a software system. | ||
|
||
* **Event**: An "event" is a data record expressing an occurrence and its context. Events are routed from an | ||
event producer (the source) to interested event consumers. | ||
|
||
* **Producer**: The "producer" is a specific instance, process or device that creates the data structure | ||
describing the CloudEvent. | ||
|
||
* **Source**: The "source" is the context in which the occurrence happened. In a distributed system it might | ||
consist of multiple producers. If a source is not aware of CloudEvents, an external producer creates | ||
the CloudEvent on behalf of the source. | ||
|
||
* **Consumer**: A "consumer" receives the event and acts upon it. It uses the context and data to execute some | ||
logic, which might lead to the occurrence of new events. | ||
|
||
* **Data**: Domain-specific information about the occurrence (i.e. the payload). This might | ||
include information about the occurrence, details about the data that was changed, or more. | ||
|
||
|
||
# API Functionality | ||
|
||
Only one endpoint/operation is provided: `POST /your_webhook_notification_url` | ||
|
||
This endpoint describes the event notification received on subscription listener side when the event occurred. A detailed description of the event notification is provided in the CAMARA API design guideline document. | ||
|
||
|
||
|
||
termsOfService: http://swagger.io/terms/ | ||
contact: | ||
email: [email protected] | ||
license: | ||
name: Apache 2.0 | ||
url: https://www.apache.org/licenses/LICENSE-2.0.html | ||
version: 0.1.0-wip | ||
externalDocs: | ||
description: Product documentation at CAMARA | ||
url: https://github.com/camaraproject/ | ||
security: | ||
- oAuth2ClientCredentials: [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aligment would be required after resolution of PR#57 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The API design guidelines allow the API consumer to have no security scheme (authorisation scheme) for event notifications. So no security also needs to be an option here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @eric-murray , There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @patrice-conil
In other words, either client credentials or no authorisation is allowed, but nothing else. When we need to send a notification, we would know which to use depending upon whether the client originally gave us a Anyway, this is just what I was expecting to see. If the client is expecting to receive notifications using some other authorisation scheme, they will be disappointed when they do not receive any. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed this one! Done! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @PedroDiez, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is an open question that, if the API consumer provides an OAuth server for their notification endpoint and advertises that in their version of this YAML, should the API implementor use this to get a token, rather than mandate that the API consumer generate a token and provide this when they create the subscription? If that is possible, then they will need to define the required scope (as well as providing the API implementor with a client id / secret). But I think the scope name is up to them. I don't see that CAMARA should impose their scope naming convention on the API consumer's own OAuth service. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Understood the point of scope of not needed to be defined in CAMARA. Regarding the point of security, the point I mention is the the token generation by API consumer is outside the Telco Operator scope. API consumer (optionalliy) provides Then, think is better an indication like this, that covers the fact of indicating in the callback such token:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @patrice-conil, @eric regarding this point: Indicating With There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @PedroDiez, @eric-murray |
||
|
||
servers: | ||
- url: '{apiRoot}' | ||
variables: | ||
apiRoot: | ||
default: http://localhost:8080 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HTTPS is mandatory for event notifications, so would be good to reflect that in the default example There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
description: Can be any notification server address sent by the client application | ||
tags: | ||
- name: Cloud Event | ||
description: | | ||
Events received on subscription listener side. | ||
paths: | ||
/your_webhook_notification_url: | ||
post: | ||
tags: | ||
- CAMARA Cloud Event notification endpoint | ||
summary: "Cloud Event notification endpoint to notify consumer that statement of fact had occurred" | ||
description: | | ||
INFORMATIVE ENDPOINT: The value of this endpoint is freely declared by each client app by means of resource-based | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
subscription or instance-based subscription. /your_webhook_notification_url is | ||
just a convention naming referring to an absolute URL, indeed the one indicated by API client | ||
in the triggering of the procedure (resource-based or instance-based). In this way, it represents an absolute | ||
URL, i.e.: notifications won't be sent to /event-notification/vX/your_webhook_notification_url. | ||
operationId: sendEvent | ||
requestBody: | ||
required: true | ||
content: | ||
application/cloudevents+json: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is correct but I think someone complained about lack of support by certain code generators. We could stick to just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to CloudEvents discussion format of "+json" is defined in RFC6839, so it should be supported by code generators. I propose to follow the CloudEvents requirement for JSON format:
|
||
schema: | ||
$ref: "#/components/schemas/CloudEvent" | ||
examples: | ||
QOS_STATUS_CHANGED_EXAMPLE: | ||
$ref: '#/components/examples/QOS_STATUS_CHANGED_EXAMPLE' | ||
|
||
responses: | ||
201: | ||
description: Created | ||
202: | ||
description: Accepted | ||
204: | ||
description: No Content | ||
200: | ||
description: Ok | ||
content: | ||
application/json: | ||
schema: | ||
type: object | ||
400: | ||
$ref: "#/components/responses/Generic400" | ||
401: | ||
$ref: "#/components/responses/Generic401" | ||
403: | ||
$ref: "#/components/responses/Generic403" | ||
410: | ||
$ref: "#/components/responses/Generic410" | ||
415: | ||
$ref: "#/components/responses/Generic415" | ||
429: | ||
$ref: "#/components/responses/Generic429" | ||
500: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generic500 can be used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
$ref: "#/components/responses/Generic500" | ||
503: | ||
$ref: "#/components/responses/Generic503" | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
components: | ||
securitySchemes: | ||
oAuth2ClientCredentials: | ||
type: oauth2 | ||
flows: | ||
clientCredentials: | ||
tokenUrl: '{tokenUrl}' | ||
scopes: {} | ||
|
||
schemas: | ||
ErrorInfo: | ||
type: object | ||
required: | ||
- status | ||
- code | ||
- message | ||
properties: | ||
status: | ||
type: integer | ||
description: HTTP response status code | ||
code: | ||
type: string | ||
description: Code given to this error | ||
message: | ||
type: string | ||
description: Detailed error description | ||
|
||
DateTime: | ||
type: string | ||
format: date-time | ||
description: Timestamp of when the occurrence happened. Must adhere to RFC 3339. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest to add in description something in this way (exact phrasing the one find more suitable), to highlight in CAMARA APIs this information is mandatory. "Optional field inCloudEvents specification. Required in CAMARA APIs implementation" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @PedroDiez, |
||
example: '2018-04-05T17:31:00Z' | ||
|
||
Source: | ||
type: string | ||
format: uri-reference | ||
minLength: 1 | ||
description: "Identifies the context in which an event happened(example: 'com.orange.camara.qod')" | ||
patrice-conil marked this conversation as resolved.
Show resolved
Hide resolved
|
||
example: | ||
- https://github.com/cloudevents | ||
- mailto:[email protected] | ||
- urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 | ||
- cloudevents/spec/pull/123 | ||
- /sensors/tn-1234567/alerts | ||
- 1-555-123-4567 | ||
patrice-conil marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
CloudEvent: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also add a discriminator explicitly to this base class schema
|
||
description: The notification callback | ||
required: | ||
- id | ||
- source | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- specversion | ||
- type | ||
patrice-conil marked this conversation as resolved.
Show resolved
Hide resolved
|
||
properties: | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
id: | ||
type: string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as long the id MUST be a non-empty string - I also recommend the constraints "minLength" here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As the format agreed is org.camaraproject... |
||
description: identifier of this event, that must be unique in the source context. | ||
minLength: 1 | ||
source: | ||
$ref: '#/components/schemas/Source' | ||
type: | ||
type: string | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
description: 'type of event as defined in each CAMARA API (e.g.: org.camara.qod.qos-status-changed-event)' | ||
example: org.camara.qod.qos-status-changed-event | ||
minLength: 15 | ||
specversion: | ||
type: string | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version) | ||
minLength: 3 | ||
datacontenttype: | ||
type: string | ||
description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' | ||
data: | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a discussion in camaraproject/QualityOnDemand#224 (comment), about whether 1) to define There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not have experience with code generators, but currently we do not have any example of subproject using events without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed for that reason we have to define "a ChildEventWithData" schema, including QoD:
DeviceStatus:
so we have to define the data per child event mandatorily always. The question was whether we should have to define it also in the base schema as optional. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jlurien, I agree with you, from an OO perspective we don't need to define it in the base schema. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So far, it is kept as optional in the CloudEvent base class. I think this is what get more consensus. If both work well with code generators, they are totally equivalent and the final schema once the composition is applied is the same. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am fine with both approaches. API Design Guidelines are "normative" for CAMARA, here we provide example that can be used by subprojects and API Consumers, but other definitions can be used if they conform to API Design Guidelines and CloudEvents specification. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please see: #43 (comment) |
||
type: object | ||
description: Event details payload described in each CAMARA API and referenced by its type | ||
subject: | ||
description: Describes the subject of the event in the context of the event producer (identified by source). | ||
type: string | ||
example: ROAMING | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should specify the subject field more detailed, so that a unified format and content is used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Current DG says that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @akoshunyadi, @rartych, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree to not make it normative by now. If we think of a usage for this property later we can add it |
||
time: | ||
$ref: "#/components/schemas/DateTime" | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To make the template even more useful, I would add also a sample schema for children events something like:
|
||
responses: | ||
Generic400: | ||
description: Problem with the client request | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
status: 400 | ||
code: "INVALID_ARGUMENT" | ||
message: "Client specified an invalid argument, request body or query param" | ||
Generic401: | ||
description: Authentication problem with the client request | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
status: 401 | ||
code: "UNAUTHENTICATED" | ||
message: "Request not authenticated due to missing, invalid, or expired credentials" | ||
Generic403: | ||
description: Client does not have sufficient permission | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
status: 403 | ||
code: "PERMISSION_DENIED" | ||
message: "Client does not have sufficient permissions to perform this action" | ||
Generic410: | ||
description: Gone | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
code: GONE | ||
message: "Access to the target resource is no longer available." | ||
Generic415: | ||
description: Unsupported Media Type | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
code: UNSUPPORTED_MEDIA_TYPE | ||
message: "The specified media type is not supported" | ||
Generic429: | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
description: Too Many Requests | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
code: TOO_MANY_REQUESTS | ||
message: "Endpoint does not support as many requests per time slot" | ||
Generic500: | ||
rartych marked this conversation as resolved.
Show resolved
Hide resolved
|
||
description: Server error | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
status: 500 | ||
code: "INTERNAL" | ||
message: "Server error" | ||
Generic503: | ||
description: Service unavailable. Typically the server is down. | ||
content: | ||
application/json: | ||
schema: | ||
$ref: "#/components/schemas/ErrorInfo" | ||
example: | ||
status: 503 | ||
code: "UNAVAILABLE" | ||
message: "Service unavailable" | ||
examples: | ||
QOS_STATUS_CHANGED_EXAMPLE: | ||
value: | ||
id: 123e4567-e89b-12d3-a456-426655440000 | ||
source: com.orange.camara.qod | ||
type: org.camara.qod.qos-status-changed-event | ||
specversion: '1.0' | ||
time: 2023-01-17T13:18:23.682Z | ||
datacontenttype: application/json | ||
data: | ||
sessionId: 6e8bc430-9c3a-11d9-9669-0800200c9a66 | ||
qosStatus: UNAVAILABLE | ||
statusInfo: DURATION_EXPIRED | ||
|
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 can remove "-wip", once we have ready for final review
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.
Done