Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty map incorrectly translates to null #1106

Open
t0yv0 opened this issue May 11, 2023 · 1 comment
Open

Empty map incorrectly translates to null #1106

t0yv0 opened this issue May 11, 2023 · 1 comment
Labels
bug/diff Bugs in computing Diffs and planning resource changes kind/bug Some behavior is incorrect or out of spec

Comments

@t0yv0
Copy link
Member

t0yv0 commented May 11, 2023

What happened?

The original issue pulumi/pulumi-aws#2517 (comment) uncovered a problem in the bridge. Under certain circumstances an empty object generated by the upstream provider turns into null on the wire when returned from the bridge, which is unexpected. A preferred form would use {} or {"field": null} possibly to represent this object.

Expected Behavior

Empty objects are represented in a way distinct from null.

Steps to reproduce

pulumi/pulumi-aws#2517 has a full repro. We also have a unit test reproducing the issue available in #1105

Output of pulumi about

CLI          
Version      3.66.0
Go Version   go1.20.3
Go Compiler  gc

Plugins
NAME    VERSION
aws     5.40.0
python  unknown

Host     
OS       darwin
Version  13.1
Arch     x86_64

This project is written in python: executable='/usr/bin/python3' version='3.9.6
'

Current Stack: t0yv0/aws-2517/dev

TYPE                            URN
pulumi:pulumi:Stack             urn:pulumi:dev::aws-2517::pulumi:pulumi:Stack::aws-2517-dev
pulumi:providers:aws            urn:pulumi:dev::aws-2517::pulumi:providers:aws::default_5_40_0
aws:ec2/vpc:Vpc                 urn:pulumi:dev::aws-2517::aws:ec2/vpc:Vpc::main
aws:lb/targetGroup:TargetGroup  urn:pulumi:dev::aws-2517::aws:lb/targetGroup:TargetGroup::test
aws:lb/targetGroup:TargetGroup  urn:pulumi:dev::aws-2517::aws:lb/targetGroup:TargetGroup::foo


Found no pending operations associated with dev

Backend        
Name           pulumi.com
URL            https://app.pulumi.com/t0yv0
User           t0yv0
Organizations  t0yv0, pulumi

Dependencies:
NAME        VERSION
pip         23.1.2
pulumi-aws  5.40.0
setuptools  67.7.2
wheel       0.40.0

Pulumi locates its logs in /var/folders/gk/cchgxh512m72f_dmkcc3d09h0000gp/T/ by default

Additional context

This may be fixed by #887

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

@t0yv0 t0yv0 added needs-triage Needs attention from the triage team kind/bug Some behavior is incorrect or out of spec and removed needs-triage Needs attention from the triage team labels May 11, 2023
@t0yv0
Copy link
Member Author

t0yv0 commented May 11, 2023

Some more context from debugging.

main.py:

import pulumi
import pulumi_aws as aws

main = aws.ec2.Vpc("main", cidr_block="10.0.0.0/16")
test = aws.lb.TargetGroup("test",
    port=80,
    protocol="HTTP",
    vpc_id=main.id)

pulumi.export('arn', test.arn)

repro.sh:

#!/usr/bin/env bash

set -euo pipefail

export AWS_PROFILE=devsandbox

pulumi destroy --yes
rm -rf *.json
pulumi up --yes --skip-preview

ARN=$(pulumi stack output arn)

# pulumi import aws:lb/targetGroup:TargetGroup foo "$ARN"

rm -rf out.txt

export PATH="/Users/t0yv0/code/pulumi-aws/bin:$PATH"

# TF_LOG=TRACE PULUMI_DEBUG_GRPC="$PWD/debug.json" pulumi import aws:lb/targetGroup:TargetGroup foo "$ARN" --yes --logtostderr --logflow -v=9 2> out.txt

PULUMI_DEBUG_GRPC="$PWD/debug.json" pulumi import aws:lb/targetGroup:TargetGroup foo "$ARN" --yes

Instrumented provider trace:

   Running v2Resource importer
    t aws_lb_target_group
    id arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2
    meta valast: cannot convert value of type func(*middleware.Stack) error
    meta type #*conns.AWSClient
    v2Results
    RESULT 0
    target_failover [] valast []interface{}{}
    runTerraformImporter returned this state
    map[id:arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2]
    map[string]interface{}{"id": "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2"}
    Before RefreshWithoutUpgrade
    &InstanceState{
        ID: "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
        Attributes: map[string]string{
                "health_check.#":    "0",
                "id":                "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
                "stickiness.#":      "0",
                "target_failover.#": "0",
        },
        Meta: map[string]interface{}{"schema_version": "0"},
    }
    outputRaw
    {
      HealthCheckEnabled: true,
      HealthCheckIntervalSeconds: 30,
      HealthCheckPath: "/",
      HealthCheckPort: "traffic-port",
      HealthCheckProtocol: "HTTP",
      HealthCheckTimeoutSeconds: 5,
      HealthyThresholdCount: 5,
      IpAddressType: "ipv4",
      Matcher: {
        HttpCode: "200"
      },
      Port: 80,
      Protocol: "HTTP",
      ProtocolVersion: "HTTP1",
      TargetGroupArn: "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
      TargetGroupName: "test-f9f76b1",
      TargetType: "instance",
      UnhealthyThresholdCount: 2,
      VpcId: "vpc-0af8bc8e0e370a7bd"
    }
    &TargetGroup{
        HealthCheckEnabled:         valast.Addr(true).(*bool),
        HealthCheckIntervalSeconds: valast.Addr(30).(*int64),
        HealthCheckPath:            valast.Addr("/").(*string),
        HealthCheckPort:            valast.Addr("traffic-port").(*string),
        HealthCheckProtocol:        valast.Addr("HTTP").(*string),
        HealthCheckTimeoutSeconds:  valast.Addr(5).(*int64),
        HealthyThresholdCount:      valast.Addr(5).(*int64),
        IpAddressType:              valast.Addr("ipv4").(*string),
        Matcher: &Matcher{
                HttpCode: valast.Addr("200").(*string),
        },
        Port:                    valast.Addr(80).(*int64),
        Protocol:                valast.Addr("HTTP").(*string),
        ProtocolVersion:         valast.Addr("HTTP1").(*string),
        TargetGroupArn:          valast.Addr("arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2").(*string),
        TargetGroupName:         valast.Addr("test-f9f76b1").(*string),
        TargetType:              valast.Addr("instance").(*string),
        UnhealthyThresholdCount: valast.Addr(2).(*int64),
        VpcId:                   valast.Addr("vpc-0af8bc8e0e370a7bd").(*string),
    }
    flattenTargetGroupFailover returns 1 element
    map[]
    map[string]interface{}{}
    After RefreshWithoutUpgrade
    &InstanceState{
        ID: "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
        Attributes: map[string]string{
                "arn":                                "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
                "arn_suffix":                         "targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
                "deregistration_delay":               "300",
                "health_check.#":                     "1",
                "health_check.0.enabled":             "true",
                "health_check.0.healthy_threshold":   "5",
                "health_check.0.interval":            "30",
                "health_check.0.matcher":             "200",
                "health_check.0.path":                "/",
                "health_check.0.port":                "traffic-port",
                "health_check.0.protocol":            "HTTP",
                "health_check.0.timeout":             "5",
                "health_check.0.unhealthy_threshold": "2",
                "id":                                 "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
                "ip_address_type":                    "ipv4",
                "load_balancing_algorithm_type":      "round_robin",
                "load_balancing_cross_zone_enabled":  "use_load_balancer_configuration",
                "name":                               "test-f9f76b1",
                "port":                               "80",
                "protocol":                           "HTTP",
                "protocol_version":                   "HTTP1",
                "slow_start":                         "0",
                "stickiness.#":                       "1",
                "stickiness.0.cookie_duration":       "86400",
                "stickiness.0.cookie_name":           "",
                "stickiness.0.enabled":               "false",
                "stickiness.0.type":                  "lb_cookie",
                "tags.%":                             "0",
                "tags_all.%":                         "0",
                "target_failover.#":                  "1",
                "target_type":                        "instance",
                "vpc_id":                             "vpc-0af8bc8e0e370a7bd",
        },
    }
    Refresh returned this state
    {0xc003622270 <nil>}
    v2InstanceState{tf: &InstanceState{
        ID: "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
        Attributes: map[string]string{
                "arn":                                "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
                "arn_suffix":                         "targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
                "deregistration_delay":               "300",
                "health_check.#":                     "1",
                "health_check.0.enabled":             "true",
                "health_check.0.healthy_threshold":   "5",
                "health_check.0.interval":            "30",
                "health_check.0.matcher":             "200",
                "health_check.0.path":                "/",
                "health_check.0.port":                "traffic-port",
                "health_check.0.protocol":            "HTTP",
                "health_check.0.timeout":             "5",
                "health_check.0.unhealthy_threshold": "2",
                "id":                                 "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-f9f76b1/b8fd8b6af0872ca2",
                "ip_address_type":                    "ipv4",
                "load_balancing_algorithm_type":      "round_robin",
                "load_balancing_cross_zone_enabled":  "use_load_balancer_configuration",
                "name":                               "test-f9f76b1",
                "port":                               "80",
                "protocol":                           "HTTP",
                "protocol_version":                   "HTTP1",
                "slow_start":                         "0",
                "stickiness.#":                       "1",
                "stickiness.0.cookie_duration":       "86400",
                "stickiness.0.cookie_name":           "",
                "stickiness.0.enabled":               "false",
                "stickiness.0.type":                  "lb_cookie",
                "tags.%":                             "0",
                "tags_all.%":                         "0",
                "target_failover.#":                  "1",
                "target_type":                        "instance",
                "vpc_id":                             "vpc-0af8bc8e0e370a7bd",
        },
    }}

Pulumi schema:

$ jq '.resources["aws:lb/targetGroup:TargetGroup"].properties["targetFailovers"]' "$S"
{
  "type": "array",
  "items": {
    "$ref": "#/types/aws:lb/TargetGroupTargetFailover:TargetGroupTargetFailover"
  },
  "description": "Target failover block. Only applicable for Gateway Load Balancer target groups. See target_failover for more information.\n"
}


jq '.types["aws:lb/TargetGroupTargetFailover:TargetGroupTargetFailover"]' "$S"
{
  "properties": {
    "onDeregistration": {
      "type": "string",
      "description": "Indicates how the GWLB handles existing flows when a target is deregistered. Possible values are `rebalance` and `no_rebalance`. Must match the attribute value set for `on_unhealthy`. Default: `no_rebalance`.\n"
    },
    "onUnhealthy": {
      "type": "string",
      "description": "Indicates how the GWLB handles existing flows when a target is unhealthy. Possible values are `rebalance` and `no_rebalance`. Must match the attribute value set for `on_deregistration`. Default: `no_rebalance`.\n"
    }
  },
  "type": "object",
  "required": [
    "onDeregistration",
    "onUnhealthy"
  ]
}

gRPC trace of the Read method.

{
  "method": "/pulumirpc.ResourceProvider/Read",
  "request": {
    "id": "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-c530e0b/6aee61b47ab16785",
    "urn": "urn:pulumi:dev::aws-2517::aws:lb/targetGroup:TargetGroup::foo",
    "properties": {}
  },
  "response": {
    "id": "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-c530e0b/6aee61b47ab16785",
    "properties": {
      "arn": "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-c530e0b/6aee61b47ab16785",
      "arnSuffix": "targetgroup/test-c530e0b/6aee61b47ab16785",
      "deregistrationDelay": 300,
      "healthCheck": {
        "enabled": true,
        "healthyThreshold": 5,
        "interval": 30,
        "matcher": "200",
        "path": "/",
        "port": "traffic-port",
        "protocol": "HTTP",
        "timeout": 5,
        "unhealthyThreshold": 2
      },
      "id": "arn:aws:elasticloadbalancing:us-east-1:616138583583:targetgroup/test-c530e0b/6aee61b47ab16785",
      "ipAddressType": "ipv4",
      "loadBalancingAlgorithmType": "round_robin",
      "loadBalancingCrossZoneEnabled": "use_load_balancer_configuration",
      "name": "test-c530e0b",
      "port": 80,
      "protocol": "HTTP",
      "protocolVersion": "HTTP1",
      "slowStart": 0,
      "stickiness": {
        "cookieDuration": 86400,
        "cookieName": "",
        "enabled": false,
        "type": "lb_cookie"
      },
      "tags": {},
      "tagsAll": {},
      "targetFailovers": [
        null
      ],
      "targetType": "instance",
      "vpcId": "vpc-02f8ca754b4d39d01"
    },
    "inputs": {
      "__defaults": [],
      "deregistrationDelay": 300,
      "healthCheck": {
        "__defaults": [],
        "healthyThreshold": 5,
        "matcher": "200",
        "path": "/",
        "timeout": 5,
        "unhealthyThreshold": 2
      },
      "ipAddressType": "ipv4",
      "loadBalancingAlgorithmType": "round_robin",
      "loadBalancingCrossZoneEnabled": "use_load_balancer_configuration",
      "name": "test-c530e0b",
      "port": 80,
      "protocol": "HTTP",
      "protocolVersion": "HTTP1",
      "stickiness": {
        "__defaults": [],
        "enabled": false,
        "type": "lb_cookie"
      },
      "targetFailovers": [
        null
      ],
      "vpcId": "vpc-02f8ca754b4d39d01"
    }
  },
  "metadata": {
    "kind": "resource",
    "mode": "client",
    "name": "aws"
  }
}

@guineveresaenger guineveresaenger removed the needs-triage Needs attention from the triage team label May 12, 2023
@t0yv0 t0yv0 added the bug/diff Bugs in computing Diffs and planning resource changes label Jun 26, 2023
@t0yv0 t0yv0 mentioned this issue Jul 7, 2023
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/diff Bugs in computing Diffs and planning resource changes kind/bug Some behavior is incorrect or out of spec
Projects
None yet
Development

No branches or pull requests

2 participants