pulumi / pulumi-aws-native

AWS Native Provider for Pulumi
Apache License 2.0
95 stars 17 forks source link

rds:DBProxyTargetGroup fails on pulumi up #872

Open jhsinger-klotho opened 1 year ago

jhsinger-klotho commented 1 year ago

What happened?

The Target group looks like it successfully creates, but then an error message causes the entire up to fail, because it seems like it cannot read the resources state

error: reading resource state: reading resource state: operation error CloudControl: GetResource, https response error StatusCode: 400, RequestID: cd1e8861-acdb-4e95-addc-927fae0ad3ee, GeneralServiceException: AWS::RDS::DBProxyTargetGroup Handler returned status FAILED: 1 validation error detected: Value null at 'dBProxyName' failed to satisfy constraint: Member must not be null (Service: AmazonRDS; Status Code: 400; Error Code: ValidationError; Request ID: 74abbfdf-4d23-40a1-b190-afdd97b2969f; Proxy: null) (HandlerErrorCode: GeneralServiceException, RequestToken: 43fe3c72-254d-4512-bebf-483f535a7273)

Expected Behavior

I would expect the up to succeed fully since it seems like the resource was created

Steps to reproduce

code used to reproduce is similar to below

const awsRdsSubnetGroupPyOrmSqllchemy = new aws.rds.SubnetGroup(`py-orm-sqllchemy`, {
        subnetIds: [awsVpcSubnetPyOrmPrivate2,awsVpcSubnetPyOrmPrivate1].map((subnet) => subnet.id),
        tags: {},
    });

const awsRdsProxyPyOrmSqllchemy = new aws.rds.Proxy(`py-orm-sqllchemy`, {
        debugLogging: false,
        engineFamily: `POSTGRESQL`,
        idleClientTimeout: 1800,
        requireTls: false,
        roleArn: awsIamRolePyOrmSqlAlchemyOrmsecretrole.arn,
        vpcSecurityGroupIds: [awsSecurityGroupPyOrm].map((sg) => sg.id),
        vpcSubnetIds: [awsVpcSubnetPyOrmPrivate2,awsVpcSubnetPyOrmPrivate1].map((subnet) => subnet.id),
        auths: [{authScheme: `SECRETS`,
iamAuth: `DISABLED`,
secretArn: awsSecretPyOrmSqlAlchemyPersistSqlAlchemy.arn,
}],
    });

const awsRdsInstancePyOrmSqlLchemy = new aws.rds.Instance(
        `py-orm-sql-lchemy`,
        {
            instanceClass: `db.t4g.micro`,
            engine: `postgres`,
            engineVersion: `13.7`,
            dbName: `sqlAlchemy`,
            username: fs.readFileSync(`secrets/persist:sqlAlchemy`, 'utf-8').split('\n')[1].split('"')[3],
            password: fs.readFileSync(`secrets/persist:sqlAlchemy`, 'utf-8').split('\n')[2].split('"')[3],
            iamDatabaseAuthenticationEnabled: true,
            dbSubnetGroupName: awsRdsSubnetGroupPyOrmSqllchemy.name,
            vpcSecurityGroupIds: [awsSecurityGroupPyOrm].map((sg) => sg.id),
            skipFinalSnapshot: true,
            allocatedStorage: 20,
        },
        { protect: protect }
    );

const awsRdsProxyTargetGroupPyOrmSqlAlchemy = new aws_native.rds.DBProxyTargetGroup(`py_orm_sqlAlchemy`, {
        dBInstanceIdentifiers: [awsRdsInstancePyOrmSqlLchemy.identifier],
        dBProxyName: awsRdsProxyPyOrmSqllchemy.name,
        connectionPoolConfigurationInfo: {connectionBorrowTimeout: 120,
maxConnectionsPercent: 100,
maxIdleConnectionsPercent: 50,
},
        targetGroupName: 'default',
    }, {
        deleteBeforeReplace: true,
    });

Output of pulumi about

CLI
Version      3.56.0
Go Version   go1.20.1
Go Compiler  gc

Plugins
NAME        VERSION
aws         5.35.0
aws-native  0.56.0
docker      4.1.2
nodejs      unknown

Host
OS       darwin
Version  12.5
Arch     arm64

Dependencies:
NAME                VERSION
@pulumi/aws-native  0.56.0
@pulumi/aws         5.35.0
@pulumi/docker      4.1.2
@pulumi/pulumi      3.62.0

Additional context

on subsequent ups we see a similar error, which my assumption is this resource requires deleteBeforeReplace to be true, which isnt the most obvious

    error: resource partially created but read failed. read error: reading resource state: operation error CloudControl: GetResource, https response error StatusCode: 400, RequestID: a5d08438-d346-42d6-b78e-0ad95c012ee8, GeneralServiceException: AWS::RDS::DBProxyTargetGroup Handler returned status FAILED: 1 validation error detected: Value null at 'dBProxyName' failed to satisfy constraint: Member must not be null (Service: AmazonRDS; Status Code: 400; Error Code: ValidationError; Request ID: 5758288e-3230-4d46-adfc-4b691315ab51; Proxy: null) (HandlerErrorCode: GeneralServiceException, RequestToken: 2e632382-724a-4fdc-bb14-5fd257d7af52), create error: operation CREATE failed with "GeneralServiceException": The target group prx-tg-0828ffa490f82255b already has other registered targets. Registering multiple targets is not supported at this time. (Service: AmazonRDS; Status Code: 400; Error Code: DBProxyTargetAlreadyRegisteredFault; Request ID: 3effe25b-9312-4d56-8a64-99309b26e7e3; Proxy: null)

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

kpitzen commented 1 year ago

Hi @jhsinger-klotho - thank you for reporting this issue and providing a complete reproduction for us! We'll get this prioritized as soon as we can.

mikhailshilkov commented 8 months ago

I compiled a full repro for this issue:

import * as aws_native from "@pulumi/aws-native";
import * as aws from "@pulumi/aws";

const dbUsername = "db_user";
const dbPassword = "...";

const vpc = new aws.ec2.Vpc("prod-vpc", {
    cidrBlock: "10.192.0.0/16",
    enableDnsSupport: true, 
    enableDnsHostnames: true,
    instanceTenancy: "default",
});

const availabilityZones = aws.getAvailabilityZones();
const subnet1 = new aws.ec2.Subnet("prod-subnet-private-1", {
    vpcId: vpc.id,
    cidrBlock: "10.192.20.0/24",
    mapPublicIpOnLaunch: false, // private
    availabilityZone: availabilityZones.then(azs => azs.names[0]),
});
const subnet2 = new aws.ec2.Subnet("prod-subnet-private-2", {
    vpcId: vpc.id,
    cidrBlock: "10.192.21.0/24",
    mapPublicIpOnLaunch: false, // private
    availabilityZone: availabilityZones.then(azs => azs.names[1]),
});
const awsRdsSubnetGroupPyOrmSqllchemy = new aws.rds.SubnetGroup(`py-orm-sqllchemy`, {
    subnetIds: [subnet1.id, subnet2.id],
    tags: {},
});

// Create an IAM role for the DB Proxy
const dbProxyRole = new aws.iam.Role("dbProxyRole", {
    assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({ Service: "rds.amazonaws.com" }),
});

// Create a secret to store database credentials
const dbCredentialsSecret = new aws.secretsmanager.Secret("dbCredentialsSecret", {
    name: "dbCredential",
});

// Store the database credentials in the secret
const dbCredentialsSecretValue = new aws.secretsmanager.SecretVersion("dbCredentialsSecretValue", {
    secretId: dbCredentialsSecret.id,
    secretString: JSON.stringify({
        username: dbUsername,
        password: dbPassword,
    }),
});

const awsRdsProxyPyOrmSqllchemy = new aws.rds.Proxy(`py-orm-sqllchemy`, {
    debugLogging: false,
    engineFamily: `POSTGRESQL`,
    idleClientTimeout: 1800,
    requireTls: false,
    roleArn: dbProxyRole.arn,
    vpcSubnetIds: [subnet1.id, subnet2.id],
    auths: [{authScheme: `SECRETS`,
        iamAuth: `DISABLED`,
        secretArn: dbCredentialsSecret.arn,
    }],
});

const awsRdsInstancePyOrmSqlLchemy = new aws.rds.Instance("py-orm-sql-lchemy", {
    instanceClass: `db.t4g.micro`,
    engine: `postgres`,
    engineVersion: `16.1`,
    dbName: `sqlAlchemy`,
    username: dbUsername,
    password: dbPassword,
    iamDatabaseAuthenticationEnabled: true,
    dbSubnetGroupName: awsRdsSubnetGroupPyOrmSqllchemy.name,
    skipFinalSnapshot: true,
    allocatedStorage: 20,
});

const awsRdsProxyTargetGroupPyOrmSqlAlchemy = new aws_native.rds.DbProxyTargetGroup(`py_orm_sqlAlchemy`, {
    dbInstanceIdentifiers: [awsRdsInstancePyOrmSqlLchemy.identifier],
    dbProxyName: awsRdsProxyPyOrmSqllchemy.name,
    connectionPoolConfigurationInfo: {connectionBorrowTimeout: 120,
maxConnectionsPercent: 100,
maxIdleConnectionsPercent: 50,
},
    targetGroupName: 'default',
}, {
    deleteBeforeReplace: true,
});

I get the same error on resource read.

I also get the same error from the AWS CLI:

aws cloudcontrol get-resource \
    --type-name AWS::RDS::DBProxyTargetGroup \
    --identifier <id>

error:

> An error occurred (GeneralServiceException) when calling the GetResource operation: AWS::RDS::DBProxyTargetGroup Handler returned status FAILED: 1 validation error detected: Value null at 'dBProxyName' failed to satisfy constraint: Member must not be null (Service: AmazonRDS; Status Code: 400; Error Code: ValidationError; Request ID: e84e7489-a5a9-42d0-8963-ac7dabbd2f93; Proxy: null) (HandlerErrorCode: GeneralServiceException, RequestToken: 0009a814-91b7-48c9-bc99-ec8047ed08f8)

or even from

aws cloudcontrol list-resources --type-name AWS::RDS::DBProxyTargetGroup 

error:

An error occurred (InvalidRequestException) when calling the ListResources operation: Missing Or Invalid ResourceModel property in AWS::RDS::DBProxyTargetGroup list handler request input. Required property: [DBProxyName]

I'll escalate to AWS for help.

mikhailshilkov commented 8 months ago

First comment from AWS:

You need to pass DBProxyName as resource-model aws cloudcontrol list-resources --type-name AWS::RDS::DBProxyTargetGroup --resource-model '{""DBProxyName"" :""something""}' What parameters need to be passed to handler are available as part of schema under list as handlerSchema Forwarding to rds team for further assistance. Pending explanation from AWS RDS team

danielrbradley commented 7 months ago

So the suggested workaround - specifying the resource model is not currently feasible because ResourceModel is not currently a property in CloudFormation. The implementation for this resource is open-sourced here: https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-rds-proxy/tree/master/aws-rds-dbproxytargetgroup

corymhall commented 2 months ago

Still an issue. Created an issue to track upstream https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/2132