serverless-appsync-plugin icon indicating copy to clipboard operation
serverless-appsync-plugin copied to clipboard

Pipeline Resolvers: Function Name and Version Issue

Open sharmmoh1983 opened this issue 6 years ago • 6 comments

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.

sharmmoh1983 avatar Feb 11 '19 04:02 sharmmoh1983

@Foosballfan ^ any thoughts?

sid88in avatar Mar 03 '19 04:03 sid88in

Can we see the Serverless input used to generate this?

Foosballfan avatar Mar 04 '19 08:03 Foosballfan

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 avatar Mar 13 '19 12:03 JustMikey

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

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

JustMikey avatar Mar 13 '19 12:03 JustMikey

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.

Foosballfan avatar Mar 14 '19 14:03 Foosballfan

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);

mattiLeBlanc avatar Sep 11 '20 05:09 mattiLeBlanc