sid88in / serverless-appsync-plugin

serverless plugin for appsync
MIT License
950 stars 186 forks source link

Pipeline Resolvers: Function Name and Version Issue #210

Open sharmmoh1983 opened 5 years ago

sharmmoh1983 commented 5 years ago

I am trying to use Pipeline feature in cloudformation but getting following errors:

Cloudformation Script:

AppSyncMarkFavoriteStoreFavoriteFunction:
      Type: AWS::AppSync::FunctionConfiguration
      Properties:
        ApiId: { Fn::GetAtt: [ GraphQLApi, ApiId ]}
        Name: storeFavorite
        DataSourceName: DynamoDB
        RequestMappingTemplate: ${file(./mapping-templates/Function-storeFavorite-request.vtl)}
        ResponseMappingTemplate: ${file(./mapping-templates/Function-storeFavorite-response.vtl)}

    AppSyncMarkFavoriteGetLocationFunction:
      Type: AWS::AppSync::FunctionConfiguration
      Properties:
        ApiId: { Fn::GetAtt: [ GraphQLApi, ApiId ]}
        Name: getLocation
        DataSourceName: DynamoDB
        RequestMappingTemplate: ${file(./mapping-templates/Function-getLocation-request.vtl)}
        ResponseMappingTemplate: ${file(./mapping-templates/Function-getLocation-response.vtl)}

    AppSyncMarkFavoriteResolver:
      Type: AWS::AppSync::Resolver
      Properties:
        ApiId: { Fn::GetAtt: [ GraphQLApi, ApiId ]}
        TypeName: Mutation
        FieldName: markFavorite
        RequestMappingTemplate: ${file(./mapping-templates/Mutation-markFavorite-request.vtl)}
        ResponseMappingTemplate: ${file(./mapping-templates/common-response.vtl)}
        PipelineConfig:
          Functions:
            - { Fn::GetAtt: [ AppSyncMarkFavoriteGetLocationFunction, FunctionName ]}
            - { Fn::GetAtt: [ AppSyncMarkFavoriteStoreFavoriteFunction, FunctionName ]}

Error: AWS::AppSync::FunctionConfiguration does not support attribute {FunctionName}

The FunctionVersion can not be null to create a function.

Eventhough it is non mandatory

Also it says after doing above fixes: The specified functions [getFunction] must exist before referencing them from a resolver.

sid88in commented 5 years ago

@Foosballfan ^ any thoughts?

Foosballfan commented 5 years ago

Can we see the Serverless input used to generate this?

JustMikey commented 5 years ago

It seems like the docs are not correct, I used Name attribute instead of FunctionName and it seems to have worked, although now I am also getting:

The specified functions [func1,func2] must exist before referencing them from a resolver

And they seem to exist and I even tried to add DependsOn attribute to make sure but that didn't help.

JustMikey commented 5 years ago

According to this thread, you should provide FunctionId instead of the function names, so it should be like this:

- { Fn::GetAtt: [ AppSyncMarkFavoriteGetLocationFunction, FunctionId ]}

Foosballfan commented 5 years ago

The pipeline resolvers were definitely working according to the docs . People have posted in this repo and let me know in person that the documented solution worked.

If anything has been changed by AWSin the required cloudformation template (or in this repository since the pipeline resolvers PR) then a PR to correct it will surely be welcomed.

If you run a new stripped down serverless deployment with the documented method and compare the resulting cloudformation template to what AWS requires then it will make any problems clear.

I will gladly assist by looking at the two cloud formation templates (as described above) if someone posts them here.

mattiLeBlanc commented 4 years ago

For people using the CDK (1.62), use attrFunctionId to setup a pipeline Config

For example:

      const resolverName = `${this.props.applicationName}-${resolver.name}`.replace(/\-/g,'_');
      const pipeLineFunctions: string[] = [];
      if (resolver.kind === ResolverKind.PIPELINE) {
        resolver.functions!.forEach(name => {
          pipeLineFunctions.push(this.pipelineFunctions[ name ].attrFunctionId);
        });
      }

      const resolverOptions: ResolverProps = {
        api: this.api,
        fieldName: resolver.name,
        typeName: resolver.type!,
        requestMappingTemplate: getTemplate(resolver, 'req', {}),
        responseMappingTemplate: getTemplate(resolver, 'res', {}),
        pipelineConfig: pipeLineFunctions,
       dataSource: ....
    };
    new Resolver(this, resolverName, resolverOptions);