sid88in / serverless-appsync-plugin Goto Github PK
View Code? Open in Web Editor NEWserverless plugin for appsync
License: MIT License
serverless plugin for appsync
License: MIT License
Hi. Maybe someone can confirm this. I have a serverless-appsync project using cognito for auth and I changed userPoolId in the serverless.yml. After I ran update-appsync no change is registered in appSync. I had to go into the AWS AppSync web console and make the changes manually.
authenticationType: AMAZON_COGNITO_USER_POOLS
userPoolConfig: #for use with COGNITO
awsRegion: us-west-2 # required # region
defaultAction: ALLOW
userPoolId: us-west-2_iswCEJijj ##<-- changes here not reflected on update-appsync
Actually I found this out because I was just using API key for auth. When I changed the auth type from API key to Cognito the value I put for userPoolId was completely wrong (I think I had a cognito ARN in there) and update-appsync did not complain. No errors or warning given.
I noticed accountId cannot be missing but as long as it present it can be any number and the deploy goes through successfully. This is a bit confusing because serverless uses the aws profile credentials to figure out which account to deploy to and this accountId in this plugin has no affect. Am I missing something here?
Deployment works in my command line but in AWS CodeBuild (image aws/codebuild/nodejs:6.3.1) it breaks. Deployment in CodeBuild works fine on serverless-appsync-plugin 0.0.6 but breaks on serverless-appsync-plugin 0.0.7.
Taking a wild guess, to me it seems probable that the old node version used in CodeBuild causes this error. I find that CodeBuild should be supported and therefore the latest node version available in CodeBuild (6.3.1) should be supported.
"serverless deploy" command breaks:
[Container] 2018/04/12 07:38:52 Running command serverless deploy -v --stage ${BUILD_LEVEL}
Serverless Error ---------------------------------------
Serverless plugin "serverless-appsync-plugin" initialization errored: Unexpected token )
"serverless update-appsync" command breaks:
[Container] 2018/04/12 07:46:06 Running command serverless update-appsync --stage ${BUILD_LEVEL}
Serverless Error ---------------------------------------
Serverless plugin "serverless-appsync-plugin" initialization errored: Unexpected token )
I was thinking that maybe the deploy and update commands should be only one.
The plugin should be able to get the apiId from the existing (if any) appsync api.
What do you think?
It would be amazing to have offline support for this :)
When I try to deploy I get the following error...
Serverless Error ---------------------------------------
Request mapping template not specified.
Since I am adapting this from the example I had tried to go through and comment out all the graphql queries/mutations/subscriptions that don't have a mapping template specified but I still get this error. It would be very helpful if the error would reference what in the graphql schema was lacking a mapping template.
Also, might it be better if unspecified mapping templates give a warning and not an error?
I'm attempting to use API_KEY authentication and I can't work out the correct format.
Looking at the code it would seem that a userPoolConfig is always required.
appSync:
authenticationType: API_KEY
.request("AppSync", "updateGraphqlApi", {
apiId: resolvedConfig.apiId,
authenticationType: resolvedConfig.authenticationType,
name: resolvedConfig.name,
userPoolConfig: {
awsRegion: resolvedConfig.region,
defaultAction: resolvedConfig.userPoolConfig.defaultAction, // userPoolConfig is null NPE
userPoolId: resolvedConfig.userPoolConfig.userPoolId
}
})
The plugin should add data sources as specified in the custom.appSync.dataSources
key in serverless.yml.
I'm proposing to slightly change the config dataSources structure to:
dataSources:
- type: AMAZON_DYNAMODB
name: Users
description: 'Users table'
config:
tableName: 'Users'
# useCallerCredentials: true # optional, applies to cognito callers
- type: AMAZON_ELASTICSEARCH
name: TweetSearch
description: 'Tweet ES'
config:
endpoint: 'Tweets'
- type: AWS_LAMBDA
name: UserAvatar
description: 'User Avatar'
config:
lambdaFunctionArn: 'arn:aws:lambda:${REGION}:${ACCOUNT_ID}:function:appsync-lambda-example'
lambda integrations for appsync
review appsync client integration code in serverless graphQL and add amplify integration (make sure all functionalities of appsync react client are included).
review existing appsync deploy code to make sure there are no errors. Can we read schema / mapping templates from text file instead of creating js objects?
On ‘serverless deploy’ it creates or updates the appsync schema. I suggest by default it uses the file ‘schema.graphql’ located in the root of the project.
Optionally the location of the schema file can be changed with a parameter nested in the custom section in serverless.yml. A possible name could be ‘graphqlSchema’
The API calls should happen after the new resources and functions are deployed so they can be referenced and it doesn’t happen that a schema goes live that doesn’t have the necessary resources up & running.
On ‘serverless remove’ the appsync schema is removed as well. Here it happens before the cloudformation stack is removed.
Note: I don’t know to much about the mappings yet. Will read up on them and we can extend/update/correct this initial draft.
Enhancement: The idea would be to optionally have just a single mapping template file for a given query/mutation. Ofter the response template is just a single line forwarding the response value anyways. Cuts down on clutter in the file tree.
Could you make apiKey
config param optional? I found that most of the time I run update-appsync to change only schema and/or mapping templates, and having to provide a valid API key for each update complicates the task, especially when you have few APIs and keys are rotated often.
Technically nothing is wrong but we need to return the callback this warning:
(node:38968) Warning: a promise was created in a handler at /Users/me/Desktop/repo/app/node_modules/serverless-appsync-plugin/index.js:403:15 but was not returned from it, see http://goo.gl/rRqMUw at new Promise (/Users/me/Desktop/repo/app/node_modules/bluebird/js/release/promise.js:79:10)
It seems like some things (like accountId) should be separated into it's a yml (or json) file that gets mapped to porcess.env. Many serious projects will need to take advantage of process.env at some point. Is there a best way to do this for aws lambdas?
Currently under userPoolConfig.userPoolId a person must enter a string for the userPool. This is great if your developing just a single AppSync system without stages. However, if using stages, you may have different user pools.
It would be great if the plugin could use
userPoolConfig:
userPoolId:
Ref: UserPool
to pull the user pool id from the resources.
Wanted to create a little discussion here for anyone interested.. to talk about a proposal for how the update/delete functionality might work in the future.
Atm there is a cleanupDataSources
function that makes an api call to AWS to find out what data sources you have on your API and compares it to the data sources you have set in your serverless.yml file. With that information it can determine what data sources aren't being used anymore and delete them. (But this could get a little bit tricky when a config grows to a large number of data sources/resolvers)
My proposal would be to; instead of making http requests to find out the data sources/resolvers needed to delete.. create a snapshot of the serverless.yml file.. and save it in a folder or something named snapshots or w/e.
With that snapshot; all you would need to do is compare locally.. that file and also your new config file that you are changing. It would determine the changes.. and make the necessary deletes to your API.
Hope we can get a few other people to weigh in on this.. and maybe share their ideas :)
Note: Snapshot files would also be good for doing rollbacks to a certain date.. or the last saved config.. or something like that as well. Maybe snapshots can have dates appended to the file names .. so u can rollback to a certain date, etc.
If anyone wants to check out the rough example I came up with on my fork you are more then welcome :) https://github.com/lolcoolkat/serverless-appsync-plugin/blob/master/index.js
I replaced the updateDataSources with a more general function (maybe should be split into multiple functions later) that cleans up the data sources/resolvers you aren't using, and also creates a snapshot at the end.. for future updates!
to see what the heck is happening
Is there a workaround to maintain multi stage setup (dev, beta, prod). apiId
is necessary for provisioning, but how do we get about providing an input with multiple apiId
depending on stage? Is an environment file the best option?
unable to look at cloudwatch logs - so debugging is hell - not sure how?
I think this repo should be re-made using https://github.com/serverless/components
It can then be deployed to the Serverless Components registry that other users can use. There are already a bunch here https://github.com/serverless/components/tree/master/registry
:)
Now AppSync has official CloudFormation support is this project redundant, should this be incorporated directly into serverless?
sls deploy-appsync
runs ok.
However, sls update-appsync
ends up as below:
Serverless: Updating GraphQL Endpoint...
Serverless: GraphQL API ID: xxxxxxxxxx
Serverless: GraphQL Endpoint: https://xxxxxxx.appsync-api.us-east-1.amazonaws.com/graphql
Serverless: Updating API Key...
Serverless Error ---------------------------------------
Missing required key 'id' in params
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Forums: forum.serverless.com
Chat: gitter.im/serverless/serverless
Your Environment Information -----------------------------
OS: darwin
Node Version: 8.9.4
Serverless Version: 1.26.1
EDIT:
Forgot to mention earlier, I do have the apiId set in serverless.yml
custom:
appSync:
apiId: xxxx
Please reach out to me :)
Thanks
Sid
I am trying to create a AppSync stack that uses just lambda functions instead of DynamoDB.
Running deploy-appsync creates the project. Every thing in this AppSync console looks good. But when I click on link to the lamba function in AWS AppSync > myApi > Data Sources it flashes an error (flashes it so quickly I cannot read it) before redirecting me to my list of lambda functions where it appears that the lambda function has not been created. When I check in the AWS CloudFormation console it also appear there is no evidence of any resources there either.
Here is my serverless.yml. It is a modified version of the example. I am thinking there is something missing from the resources section?
provider:
name: aws
runtime: nodejs6.10
region: us-west-2
functions:
hello:
handler: handler.hello
plugins:
- serverless-appsync-plugin
custom:
accountId: [redacted] # found here https://console.aws.amazon.com/billing/home?#/account
appSync:
name: serverlessAPI # defaults to api
authenticationType: AMAZON_COGNITO_USER_POOLS
userPoolConfig:
awsRegion: us-west-2 # required # region
defaultAction: ALLOW
userPoolId: us-west-2_SHawmnz0D # required # user pool ID
region: us-west-2 # defaults to provider region
mappingTemplatesLocation: mapping-templates # defaults to mapping-templates
mappingTemplates:
- dataSource: Serverless_Lambda_DS # data source name
type: Query # Query, Mutation, Subscription
field: getUserInfo
request: getUserInfo-request-mapping-template.txt # request mapping template name
response: getUserInfo-response-mapping-template.txt # response mapping template name
schema: schema.graphql # defaults schema.graphql
serviceRole: "AppSyncServiceRole"
dataSources:
- type: AWS_LAMBDA
name: Serverless_Lambda_DS # data source name
description: 'Lambda DataSource'
config:
lambdaFunctionArn: "arn:aws:lambda:us-west-2:${self:custom.accountId}:function:serverless-lambda-dev-graphql"
serviceRoleArn: "arn:aws:iam::${self:custom.accountId}:role/Lambda-${self:custom.appSync.serviceRole}"
resources:
Resources:
AppSyncLambdaServiceRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "Lambda-${self:custom.appSync.serviceRole}"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "appsync.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
-
PolicyName: "Lambda-${self:custom.appSync.serviceRole}-Policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "lambda:invokeFunction"
Resource:
- "arn:aws:lambda:us-west-2:${self:custom.accountId}:function:serverless-lambda-dev-graphql"
- "arn:aws:lambda:us-west-2:${self:custom.accountId}:function:serverless-lambda-dev-graphql:*"```
Just a quick note to say I'm going to be working on making the resolver mappings a bit more generalized.
Am I right to think that the serverless.yml should drive the resolver mappings? i.e.:
mappingTemplates:
- dataSource: Tweets
type: User
field: topTweet
request: "topTweet-request-mapping-template.txt"
response: "topTweet-response-mapping-template.txt"
- dataSource: Users
type: Query
field: meInfo
request: "meInfo-request-mapping-template.txt"
response: "meInfo-response-mapping-template.txt"
...
I'm encountering an "Invalid endpoint configuration" error when I attempt to deploy a new AppSync API with an ElasticSearch domain as my data source.
The ES domain is on the same AWS account, has been created, and is ready for use. The custom
part of my serverless.yml file is below, and the endpoint
parameter was copy/pasted into it.
custom:
accountId: [REDACTED]
appSync:
name: [REDACTED]
authenticationType: API_KEY
serviceRole: "AppSyncServiceRole"
region: [REDACTED]
schema: schema.graphql
dataSources:
- type: AMAZON_ELASTICSEARCH
name: [REDACTED]
config:
endpoint: https://vpc-[REDACTED]-[REDACTED].[REDACTED].es.amazonaws.com
serviceRoleArn: "???"
I have tried several different serviceRoleArns but nothing seems to make a difference.
What am I doing wrong? I'm pulling my hair out here.
we need testing to make sure all use cases are covered https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/AppSync.html
const serviceRoleElastic = arn:aws:iam::${accountId}:role/${roleNameElastic}
; // Service IAM Role for appsync to access data sources
const serviceRoleDynamo = arn:aws:iam::${accountId}:role/${roleNameDynamo}
; // Service IAM Role for appsync to access data sources
you may have 2 or more service roles and each data source is associated with 1 role:
const datasourceParams = [
{
apiId: appId /* required */,
name: 'elastic' /* required */,
type: 'AMAZON_ELASTICSEARCH' /* required */,
description: 'my first data source',
elasticsearchConfig: {
awsRegion: awsRegion /* required */,
endpoint: esEndpoint /* required */,
},
serviceRoleArn: serviceRoleElastic,
},
{
apiId: appId /* required */,
name: 'Users' /* required */,
type: 'AMAZON_DYNAMODB' /* required */,
description: 'Store user info',
dynamodbConfig: {
awsRegion: awsRegion /* required */,
tableName: 'ESUsers' /* required */,
},
serviceRoleArn: serviceRoleDynamo,
},
];
taking example below from readme of appsync plugin:
serviceRole: # required - example: "arn:aws:iam::${self:custom.accountId}:role/EXAMPLE-Role"
dataSources:
- type: AMAZON_DYNAMODB
name: Users
description: 'Users table'
config:
tableName: 'Users'
how do we test subscription in dynamodb example
First, thank you for developing this great plugin. I have been setting up Appsync over the last week and it is awesome to use, given there is a good bit of trial/error, due to limited Appsync documentation.
I have run into a bug, possibly due to recent changes to Appsync. When you run the sls update-appsync and you have a "Lambda Data Source" (for a Lambda based resolver), it drops the role after each update. Deploy seem to work. So every time I run update-appsync, I have to go click the dropdown in datasource and set the Region, Function Arn, and role to make every work. The update throws no errors, and was a pain to chase down when my query just stopped working.
Right after an update (before I set the ARNs/Role) the Lambda Resolver returns: java.lang.IllegalArgumentException: Illegal ARN format detected, the relative-id must follow the format function::
-Michael
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.