hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.86k stars 9.2k forks source link

[Bug]: Apply error "PipelineConfig can't be null" when creating an Appsync Resolver without any functions #35409

Open nicholasrobertson opened 10 months ago

nicholasrobertson commented 10 months ago

Terraform Core Version

v1.3.5

AWS Provider Version

v5.33.0

Affected Resource(s)

aws_appsync_resolver

Expected Behavior

I should have a pipeline resolver created without any functions

I am able to do this in the AWS console without any issues

Actual Behavior

When I try and create a PIPELINE resolver, without any functions, aws appsync returns an apply error

Relevant Error/Panic Output Snippet

Error: creating AppSync Resolver: BadRequestException: PipelineConfig can't be null. { RespMetadata: { StatusCode: 400, RequestID: "7e046c0c-1d0a-4179-a011-34a062f39b05" }, Message_: "PipelineConfig can't be null." }
with aws_appsync_resolver.foo
on debug.tf line 16, in resource "aws_appsync_resolver" "foo":
resource "aws_appsync_resolver" "foo"

Terraform Configuration Files

resource "aws_appsync_graphql_api" "foo" {
    authentication_type = "API_KEY"
    name                = "empty_pipeline_issue"
    schema              = <<EOF
        schema {
            query: Query
        }

        type Query {
            foo: String
        }
    EOF

}

resource "aws_appsync_resolver" "foo" {
  type   = "Query"
  api_id = aws_appsync_graphql_api.foo.id
  field  = "foo"
  kind   = "PIPELINE"
  code   = <<EOF
        export function request(ctx) {
            return {};
        }

        export function response(ctx) {
            return "bar";
        }
    EOF

  runtime {
    name            = "APPSYNC_JS"
    runtime_version = "1.0.0"
  }

  pipeline_config {
    functions = [
    ]
  }
}

Steps to Reproduce

run from terraform cloud observe error

Debug Output

No response

Panic Output

No response

Important Factoids

I am not a go programmer sorry but expect that potentially need to send a pipeline config with and empty functions array.

References

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appsync_graphql_api

Would you like to implement a fix?

No

github-actions[bot] commented 10 months ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

justinretzolk commented 10 months ago

Similar #15480

nicholasrobertson commented 10 months ago

@justinretzolk - its similiar but there is no circular dependency issue here. The issue here seems to be that pipleline config is not sent to the aws api?

nicholasrobertson commented 10 months ago

@justinretzolk , maybe just need to parse and empty array 'functions' when the array has 0 entries?

i.e maybe change if v, ok := m["functions"].([]interface{}); ok && len(v) > 0 { to if v, ok := m["functions"].([]interface{}); ok && len(v) >= 0 {

https://github.com/hashicorp/terraform-provider-aws/blob/main/internal/service/appsync/resolver.go#L436C53-L436C62

I'm not super confident this is the root cause or will fix it, maybe there could be some issue in the aws SDK / API also, but worth a try?

justinretzolk commented 10 months ago

Hey @nicholasrobertson 👋 I'm the community manager for the provider, so my comment was more for triaging for our tracking than anything 🙂. That said, I took a quick look, and the pipeline_config block and even the functions argument within it are optional, so unless there's something I've overlooked, you should be able to omit them from the config entirely (shown below). Can you try that and see if that resolves the issue?

resource "aws_appsync_resolver" "foo" {
  type   = "Query"
  api_id = aws_appsync_graphql_api.foo.id
  field  = "foo"
  kind   = "PIPELINE"
  code   = <<EOF
        export function request(ctx) {
            return {};
        }

        export function response(ctx) {
            return "bar";
        }
    EOF

  runtime {
    name            = "APPSYNC_JS"
    runtime_version = "1.0.0"
  }
}
vine-mxm commented 9 months ago

hi @justinretzolk i'm very new to terraform so i could be wrong but i think i'm experiencing the same issue as @nicholasrobertson

this is the output of the terraform plan

  + resource "aws_appsync_resolver" "this" {
      + api_id            = "api_id_value(removed by me 4 security purpose)"   
      + arn               = (known after apply)
      + field             = "getUserMissions"
      + id                = (known after apply)
      + kind              = "PIPELINE"
      + request_template  = <<-EOT
            {
                "version" : "2017-02-28",
                "operation" : "Query",
                "query" : {
                    ## Provide a query expression. **        
                    "expression": "userId_missionId = :a and begins_with(id,:b)",
                    "expressionValues" : {
                        ":a" : $util.dynamodb.toDynamoDBJson($ctx.args.userId),
                        ":b" : { "S": "COUNTER" }
                         }
                }
            }
        EOT
      + response_template = <<-EOT
            {
                "items": $util.toJson($ctx.result.items),
                "nextToken": $util.toJson($util.defaultIfNullOrBlank($context.result.nextToken, null))
            }
        EOT
      + type              = "Query"
    }

i don't see any pipeline_config block but i still get the same error. is this useful? i can provide more context if needed!

mleziva commented 3 months ago

I am encountering the same issue:

  ~ resource "aws_appsync_resolver" "this" {
        id                = "5jkdxsdrwvhrvngw7ndokymn6i-Query-test"
        # (10 unchanged attributes hidden)

      - pipeline_config {
          - functions = [
              - "uys6yj53yrf412gsda4zsw67u",
            ] -> null
        }

        # (1 unchanged block hidden)
    }

│ Error: updating AppSync Resolver (4gkdxsdrwvhrvngw7ndokymn6i-Query-userAccountInfo): operation error AppSync: UpdateResolver, https response error StatusCode: 400, RequestID: eb54af95-08b0-4fb6-b002-364d393353f4, BadRequestException: PipelineConfig can't be null.

Based on the fact that it returns a 400 error, I would assume this is actually coming from the AWS API so even though the Terraform Provider code marks this as optional, it is required by the AWS API. Including the pipeline_config with an empty functions array works as expected

mleziva commented 3 months ago

@justinretzolk, looks like there is also a bug in the provider when pipeline_config is provided with empty functions. The initial apply works but a subsequent apply shows changes and then crashes

Repro steps:

  1. Deploy aws_appsync_resolver with pipeline_config containing an empty functions array
  2. After apply is successful, run apply again and note changes are detected
  3. Apply fails with error

Changes shown on second apply:

  ~ resource "aws_appsync_resolver" "this" {
        id                = "5jkdxsdrwvhrvngw7ndokymn6i-Query-test"
        # (10 unchanged attributes hidden)

      + pipeline_config {
          + functions = []
        }

        # (1 unchanged block hidden)
    }
│ Error: Plugin did not respond
│ 
│   with module.appsync[0].aws_appsync_resolver.this["Query.test"],
│   on modules/appsync/main.tf line 98, in resource "aws_appsync_resolver" "this":
│   98: resource "aws_appsync_resolver" "this" {
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵

Stack trace from the terraform-provider-aws_v5.60.0_x5 plugin:

panic: interface conversion: interface {} is nil, not map[string]interface {}

goroutine 73 [running]:
github.com/hashicorp/terraform-provider-aws/internal/service/appsync.resourceResolverUpdate({0x1197127c8, 0x14002b6bdd0}, 0x14002b6c300, {0x119461ac0, 0x140029a6270})
        github.com/hashicorp/terraform-provider-aws/internal/service/appsync/resolver.go:328 +0xc5c
github.com/hashicorp/terraform-provider-aws/internal/provider.New.(*wrappedResource).Update.interceptedHandler[...].func10(0x14002b6c300?, {0x119461ac0?, 0x140029a6270})
        github.com/hashicorp/terraform-provider-aws/internal/provider/intercept.go:113 +0x1d8
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).update(0x1197127c8?, {0x1197127c8?, 0x14002b52e70?}, 0xd?, {0x119461ac0?, 0x140029a6270?})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.34.0/helper/schema/resource.go:835 +0x64
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).Apply(0x14000b13dc0, {0x1197127c8, 0x14002b52e70}, 0x14004a83860, 0x14002b6c180, {0x119461ac0, 0x140029a6270})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.34.0/helper/schema/resource.go:947 +0x670
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ApplyResourceChange(0x140041c2390, {0x1197127c8?, 0x14002b52db0?}, 0x1400082c140)
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.34.0/helper/schema/grpc_provider.go:1153 +0xaa4
github.com/hashicorp/terraform-plugin-mux/tf5muxserver.(*muxServer).ApplyResourceChange(0x14000d9f8f0, {0x1197127c8?, 0x14002b52ae0?}, 0x1400082c140)
        github.com/hashicorp/terraform-plugin-mux@v0.16.0/tf5muxserver/mux_server_ApplyResourceChange.go:36 +0x184
github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server.(*server).ApplyResourceChange(0x14001b0b0e0, {0x1197127c8?, 0x14002b52120?}, 0x14000db4770)
        github.com/hashicorp/terraform-plugin-go@v0.23.0/tfprotov5/tf5server/server.go:865 +0x2b4
github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ApplyResourceChange_Handler({0x11924f0e0, 0x14001b0b0e0}, {0x1197127c8, 0x14002b52120}, 0x14000981200, 0x0)
        github.com/hashicorp/terraform-plugin-go@v0.23.0/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:518 +0x1c0
google.golang.org/grpc.(*Server).processUnaryRPC(0x140010a0200, {0x1197127c8, 0x14002b52090}, {0x119774980, 0x14000298300}, 0x14002b465a0, 0x14002a382d0, 0x122b9d4f8, 0x0)
        google.golang.org/grpc@v1.63.2/server.go:1369 +0xb58
google.golang.org/grpc.(*Server).handleStream(0x140010a0200, {0x119774980, 0x14000298300}, 0x14002b465a0)
        google.golang.org/grpc@v1.63.2/server.go:1780 +0xb20
google.golang.org/grpc.(*Server).serveStreams.func2.1()
        google.golang.org/grpc@v1.63.2/server.go:1019 +0x8c
created by google.golang.org/grpc.(*Server).serveStreams.func2 in goroutine 16
        google.golang.org/grpc@v1.63.2/server.go:1030 +0x13c

Error: The terraform-provider-aws_v5.60.0_x5 plugin crashed!