pulumi / pulumi

Pulumi - Infrastructure as Code in any programming language πŸš€
https://www.pulumi.com
Apache License 2.0
21.26k stars 1.1k forks source link

Terraform conversion bug - cannot assign expression of type #16345

Closed rohanpower closed 3 months ago

rohanpower commented 3 months ago

What happened?

Attempting to run pulumi convert --from terraform --language python --out converted, however receiving the error output below.

Example

Pulumi Version:   v3.119.0
error: network.pp:0,42-4,2: cannot assign expression of type { tags: ({ name: string }) } to location of type   {
    cidrBlock: output(string) | output(string?) | string?,
    default: bool | output(bool) | output(bool?)?,
    dhcpOptionsId: output(string) | output(string?) | string?,
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    id: output(string) | output(string?) | string?,
    state: output(string) | output(string?) | string?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    cidrBlock: string?,
    default: bool?,
    dhcpOptionsId: string?,
    filters: list({ name: string?, values: list(string)? })?,
    id: string?,
    state: string?,
    tags: map(string)?,
  }): ;
error: main.pp:155,49-163,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    mostRecent: bool | output(bool) | output(bool?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    mostRecent: bool?,
    tags: map(string)?,
  }): ;
error: main.pp:173,53-181,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    getPasswordData: bool | output(bool) | output(bool?)?,
    getUserData: bool | output(bool) | output(bool?)?,
    instanceId: output(string) | output(string?) | string?,
    instanceTags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    getPasswordData: bool?,
    getUserData: bool?,
    instanceId: string?,
    instanceTags: map(string)?,
    tags: map(string)?,
  }): ;
error: main.pp:189,56-197,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    getPasswordData: bool | output(bool) | output(bool?)?,
    getUserData: bool | output(bool) | output(bool?)?,
    instanceId: output(string) | output(string?) | string?,
    instanceTags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    getPasswordData: bool?,
    getUserData: bool?,
    instanceId: string?,
    instanceTags: map(string)?,
    tags: map(string)?,
  }): ;
error: main.pp:199,52-207,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    mostRecent: bool | output(bool) | output(bool?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    mostRecent: bool?,
    tags: map(string)?,
  }): ;
error: main.pp:215,53-223,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    getPasswordData: bool | output(bool) | output(bool?)?,
    getUserData: bool | output(bool) | output(bool?)?,
    instanceId: output(string) | output(string?) | string?,
    instanceTags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    getPasswordData: bool?,
    getUserData: bool?,
    instanceId: string?,
    instanceTags: map(string)?,
    tags: map(string)?,
  }): ;
error: main.pp:225,53-233,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    mostRecent: bool | output(bool) | output(bool?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    mostRecent: bool?,
    tags: map(string)?,
  }): ;
error: main.pp:235,54-243,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    mostRecent: bool | output(bool) | output(bool?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    mostRecent: bool?,
    tags: map(string)?,
  }): ;
error: main.pp:245,54-253,2: cannot assign expression of type { filters: ({ name: string, values: (string) }), tags: ({ name: string }) } to location of type   {
    filters:   list(  {
          name: output(string) | output(string?) | string?,
          values:   list(output(string) | string)
          | output(list(string))
          | output(list(string)?)?,
        }
      | output({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? }))
    | output(list({ name: string?, values: list(string)? })?)?,
    mostRecent: bool | output(bool) | output(bool?)?,
    tags: map(output(string) | string) | output(map(string)) | output(map(string)?)?,
  }
| output({
    filters: list({ name: string?, values: list(string)? })?,
    mostRecent: bool?,
    tags: map(string)?,
  }): ;
warning: network.pp:117,10-119,5: ; Cannot assign value ({ name: string }) to attribute of type "Optional<Map<string>>" for resource "aws:ec2:SecurityGroup"
error: could not generate output program

Output of pulumi about

CLI
Version      3.119.0
Go Version   go1.22.3
Go Compiler  gc

Host     
OS       ubuntu
Version  22.04
Arch     x86_64

Additional context

No response

Contributing

Vote on this issue by adding a πŸ‘ reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

justinvp commented 3 months ago

Thanks for opening the issue, @rohanpower, and sorry for the trouble!

Is it possible to share the TF code you're trying to convert? Or a reduce version of it that still errors? Thanks!

rohanpower commented 3 months ago

Hi @justinvp

This excerpt is from the network.tf file:

data "aws_vpc" "_0000mgmt" {
  tags {
    Name = "1111-mgmt-vpc-apse2"
  }
}

data "aws_vpc_peering_connection" "_0000prod" {
  id = "pcx-2222222222222" //no name to seach on
}

data "aws_vpc_peering_connection" "_0000npe" {
  id = "pcx-3333333333333" //no name to seach on
}

data "aws_vpn_gateway" "vpn" {
  attached_vpc_id = "${data.aws_vpc._0000mgmt.id}"

  # state = "attached"
}

data "aws_ec2_transit_gateway" "general" {
  id = "tgw-4444444444444" //no name to seach on
}

data "aws_subnet" "_0000mgmt_c" {
  vpc_id            = "${data.aws_vpc._0000mgmt.id}"
  availability_zone = "ap-southeast-2c"

  filter {
    name   = "tag:Name"
    values = ["*_0000mgmt*"]
  }
}

data "aws_subnet" "_9999mgmt" {
  vpc_id = "${data.aws_vpc._0000mgmt.id}"

  filter {
    name   = "tag:Name"
    values = ["*9999mgmt*"]
  }
}

data "aws_subnet" "_0000mgmt_b" {
  vpc_id            = "${data.aws_vpc._0000mgmt.id}"
  availability_zone = "ap-southeast-2b"

  filter {
    name   = "tag:Name"
    values = ["*_0000mgmt*"]
  }
}

resource "aws_security_group" "_1111_mgmt_ABC_sg_apse2" {
  name        = "1111_mgmt_ABC_sg_apse2"
  description = "Allow all inbound traffic"
  vpc_id      = "${data.aws_vpc._0000mgmt.id}"

  ingress {
    from_port   = "-1"
    to_port     = "-1"
    protocol    = "icmp"
    cidr_blocks = ["10.0.0.0/8"]
  }

  ingress {
    from_port   = 3389
    to_port     = 3389
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/8"]
  }

  ingress {
    from_port   = 53
    to_port     = 53
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/8"]
  }

  ingress {
    from_port   = 389
    to_port     = 389
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/8"]
  }

  egress {
    cidr_blocks = ["10.3.8.11/32"]
    description = ""
    from_port   = "0"
    protocol    = "-1"
    to_port     = "0"
  }

  egress {
    cidr_blocks = ["10.1.22.167/32", "10.2.2.12/32"]
    description = "9001"
    from_port   = "9001"
    protocol    = "tcp"
    to_port     = "9001"
  }

  egress {
    cidr_blocks = ["10.1.22.167/32", "10.2.2.12/32"]
    description = "22"
    from_port   = "22"
    protocol    = "tcp"
    to_port     = "22"
  }

  egress {
    cidr_blocks = ["10.1.0.0/16"]
    description = "Prod-9001"
    from_port   = "9001"
    protocol    = "tcp"
    to_port     = "9001"
  }

  egress {
    cidr_blocks = ["10.1.0.0/16"]
    description = "Prod-443"
    from_port   = "443"
    protocol    = "tcp"
    to_port     = "443"
  }

  egress {
    cidr_blocks = ["10.1.0.0/16"]
    description = "Prod-80"
    from_port   = "80"
    protocol    = "tcp"
    to_port     = "80"
  }

  egress {
    cidr_blocks = ["10.2.36.50/32"]
    description = "Server Access"
    from_port   = "0"
    protocol    = "tcp"
    to_port     = "65535"
  }

  tags {
    Name = "1111_mgmt_ABC_sg_apse2"
  }

  lifecycle {
    prevent_destroy = true
  }
}
tgummerer commented 3 months ago

Hi @rohanpower, I gave this a try locally, and it looks like the terraform file you're providing is not valid, and thus pulumi can't convert it.

tags is not a block, but it's a variable that is getting a map assigned. E.g. instead of

data "aws_vpc" "_0000mgmt" {
  tags {
    Name = "1111-mgmt-vpc-apse2"
  }
}

you need to have

data "aws_vpc" "_0000mgmt" {
  tags = {
    Name = "1111-mgmt-vpc-apse2"
  }
}

Fixing all the tags variables up this way pulumi succeeds to convert the above example correctly.

I'm going to close this issue out, since this seems to be working as designed, but please let us know if you have any further trouble.

rohanpower commented 3 months ago

Thanks @tgummerer @justinvp . The version of Terraform these scripts were originally written in was v0.11.11. Was hoping it wouldn't have to, but I'll have to spend some time upgrading them to at least v1.5.7