-
Notifications
You must be signed in to change notification settings - Fork 4k
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: add support for defining/importing api gateway models #2102
feat: add support for defining/importing api gateway models #2102
Conversation
cc477ef
to
ff7ca01
Compare
In order to get the |
/** | ||
* Interface share for creating or importing a model. | ||
*/ | ||
export interface IModelConstruct extends cdk.IConstruct, IModel { |
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 IModel
should be the IConstruct
sub interface. I'm not sure what you mean when you talk about simple text reference on the comment of IModel
itself...
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.
When I initially added the IModel
interface, it was providing support just for the default Empty and Error models that are generated by default for a REST API. In that pull request, the EmptyModel
and ErrorModel
types were not set up to implement the Construct
type, in the interest of keeping things simple. I can try to look into a low-impact way to converge on one IModel interface.
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've been looking at this, and it seems weird to require the EmptyModel
and ErrorModel
classes to extend the full Construct class, when they are just there to be able to return "Empty" and "Error", for method responses using these built-in models.
I can, but it may just mean that I would stop exporting those types, and only expose them as static properties on the Model
class. If that seems best, I can do it, and then converge things down to one interface.
At the moment, I've changed the naming around:
IModel
->IModelRef
refers to the base interface that just exposes a model ID. Used for (EmptyModel
,ErrorModel
)IModelConstruct
->IModel
now refers to the full interface that inherits fromIConstruct
. Used for (Model
andImportedModel
)
/** | ||
* Model CFN resource |
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.
That comment shouldn't be necessary, as the CfnModel
class would already encapsulate this information.
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.
Removed the comment.
*/ | ||
public get referenceForSchema(): string { | ||
return `https://apigateway.amazonaws.com/restapis/${this.restApi.restApiId}/models/${this.modelId}`; |
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.
Might need to use cdk.Aws.urlSuffix
instead of amazonaws.com
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.
Sure. I can change that.
* @param schema The schema to use to transform data to one or more output formats. | ||
* @param description A description that identifies this model. | ||
*/ | ||
public addModel(name: string, contentType: string, schema: any, description?: string): Model { |
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.
You should wrap contentType
, schema
, and description?
in a "props" type object.
Also, I would advise against using any
for the schema
. You will not be able to export the type from jsonschema
(if you decide to go with it) because it is not a JSII module... But I guess you could duplicate it (it's not ideal, but it's pragmatic).
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.
Yeah. I was definitely trying to add that type safety to the schema before, but was running into those JSII errors. I'll try your suggestion around adding jsonschema to the bundledDependencies.
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 was toying with creating a duplicate of the JSONschema type. The JSII linting rules were not fond of the $schema
and $ref
properties, as they were detected as not conforming to camelCasing.
Perhaps this could be handled by removing those $ characters from the interface, and then transforming the schema property on Model into an object matching the JSON schema spec, with the $ prefixed properties.
const method = api.beer.addMethod('GET', getBeerLambdaHandler, { | ||
methodResponses: [{ | ||
statusCode: '200', | ||
responseModels: { |
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 model seems to know what content type it supports. Is there a more concise api that can take advantage of this (something like “addResponseModel”?
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.
Yeah, that seems like a useful way to help steer people away from accidental content type mismatches.
|
||
```ts | ||
// Direct addition to REST API | ||
const beerModel = api.addModel('Beer', 'application/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.
Use keyword arguments instead of positional (basically extract the common options from ModelProps and reuse 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.
Done.
* The ID of a REST API with which to associate this model. | ||
* Required. | ||
*/ | ||
restApi: IRestApi, |
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.
Use semi-colons instead of commas
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.
* Required. | ||
* @see http://json-schema.org/ | ||
*/ | ||
schema: any, // TODO: Validate that the schema provided matches the JSON schema spec. |
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.
Yes please!
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.
Working on it, but JSII linting does not like the $ref
and $schema
properties in my JsonSchema interface. Attempting to remove those from the interface, but transform the output schema object to use $schema and $ref. It's getting kind of ugly with all the recursive properties...
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.
Alright, I've got a little mapper class to take care of transforming the ref
and schema
properties to include the $ prefix.
* Defines a reference to a model created outside of the current CloudFormation stack. | ||
*/ | ||
export class ImportedModel extends cdk.Construct implements IModelConstruct { |
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.
Shouldn’t be exported
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.
Removed the export.
@@ -82,7 +82,9 @@ | |||
}, | |||
"awslint": { | |||
"exclude": [ | |||
"resource-attribute:@aws-cdk/aws-apigateway.IRestApi.restApiRootResourceId" | |||
"resource-attribute:@aws-cdk/aws-apigateway.IRestApi.restApiRootResourceId", | |||
"resource-interface-extends-construct:@aws-cdk/aws-apigateway.IModel", |
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 see a good reason to exclude these
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 ties into my explanation to @RomainMuller's comment above about the two interfaces for model. The original IModel was added to start getting model support in for MethodResponse, but only going as far as helping to allow the default Empty and Error models to be referenced. I didn't think it necessarily made sense to complicate those model types by making them implement Construct. That said, as above, I can look into what's needed to converge these into one interface. In which case, I will remove this exclusion.
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 was originally getting build errors on the IModel
interface, with those complaints about extending construct and including an export() method, but I don't seem to be now. So, I've removed the exclusions. 🤷♂️
ec33e0b
to
b1bdb3d
Compare
@RomainMuller and @eladb, I've made an attempt to address all your requests/comments above. Most of it was pretty straight forward. However, there are a couple of things that I'm still a bit unsure of:
|
abfb8a9
to
fb1615d
Compare
…h a single test. Add a test for adding a model with valid JSON schema. Document some test cases. Add support for optional model name/description properties. Add test for consumption of a model in a MethodResponse. Add test case for importing an existing model, and using it. Clean up testing todo list. Add test case for exporting a model. Update formatting from 4 to 2 spaces. Create IModelConstruct to expose IConstruct properties on concrete implementations of IModel. Fix tests from rebase to updated master. Add method to RestApi to direclty add a model. Tweak some documentation and add an integration test for an API with defined models. Expose property on model that can be used to generate a canonical reference for another external model to consume. Correct typo in README, and add some comments into code sample. Update comments and make minor syntactic changes. Split ModelProps into two interfaces to handle the constructor vs addModel method cases. Clean up IModel awslint exclusions. Rename IModel -> IModelRef, and IModelConstruct -> IModel. Add JSON schema type safety to the schema property of Model. Fix test errors after merge with 'master'
…type to be inferred from a created model. Fix methodresponse usage in README, and update formatting of integration test expected files. Convert JsonSchemaSchema enum to a static class, to fix build errors. Fix README for changes in JsonSchemaSchema, again.
fb1615d
to
3161b42
Compare
Adds support to @aws-cdk/api-gateway module to define one or more models, attached to a given REST API.
Note: Did not yet add JSON schema validation for the
schema
property. Toyed with thejsonschema
Node module, but that wouldn't work, due to the lack of JSII support. Open to some suggestions on this, if this problem has been tackled elsewhere in CDK.Addresses issue: #1695
Pull Request Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.