aws-redshift-alpha: Race condition when adding table and granting permission in same deployment
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
When trying to add a new table to a Redshift database AND also grant an existing user permission to that table in the same deployment, the deployment would fail due to the `GRANT` query executing before the table has has been added, leading to `ERROR: relation "new_table" does not exist"`.
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Last Known Working CDK Version
_No response_
### Expected Behavior
New table is created _then_ permission is granted to user.
### Current Behavior
`TablePrivileges` resource update gets initiated _while_ new table is still in `CREATE_IN_PROGRESS`, leading to deployment failure with message:
```
Received response status [FAILED] from custom resource. Message returned: Statement status was FAILED: ERROR: relation "new_table" does not exist
```
### Reproduction Steps
Create cluster with at least one table and user and grant permissions to tables. Deploy this code to CF:
```
const user = new User(this, 'User', {
cluster,
databaseName,
adminUser,
username: 'service_user',
});
const tables = [
new Table(this, 'OldTable', {
tableName: 'existing_table',
tableColumns: [ ... ],
cluster,
databaseName,
adminUser,
distStyle: TableDistStyle.KEY,
});
]
tables.forEach((table) => {
user. addTablePrivileges(table, TableAction.SELECT, TableAction.INSERT);
});
```
Once the previous code finish deployment, add a new table to `tables` list, then attempt to deploy the new change:
```
const user = new User(this, 'User', {
cluster,
databaseName,
adminUser,
username: 'service_user',
});
const tables = [
new Table(this, 'OldTable', {
tableName: 'existing_table',
tableColumns: [ ... ],
cluster,
databaseName,
adminUser,
distStyle: TableDistStyle.KEY,
});
new Table(this, 'NewTable', {
tableName: 'new_table',
tableColumns: [ ... ],
cluster,
databaseName,
adminUser,
distStyle: TableDistStyle.KEY,
});
]
tables.forEach((table) => {
user. addTablePrivileges(table, TableAction.SELECT, TableAction.INSERT);
});
```
Deployment would fail due to race condition between adding new table and granting new permission.
### Possible Solution
Permission grant need to wait for table to finish deployment.
This may be due to dependency chain not being setup correctly. Even though there is a dependency setup between `UserTablePrivileges` and the table, it only seems to be added for the first privilege defined: https://github.com/aws/aws-cdk/blob/v2.190.0/packages/%40aws-cdk/aws-redshift-alpha/lib/user.ts#L117
### Additional Information/Context
_No response_
### CDK CLI Version
cdk: 2.181.0 | aws-redshift-alpha: 2.181.0-alpha.0
### Framework Version
v18.18.2
### Node.js Version
v18.18.2
### OS
MacOS
### Language
TypeScript
### Language Version
TypeScript (5.0.4)
### Other information
_No response_
Contributor guide
Research direction
Start in packages/@aws-cdk/aws-redshift-alpha/lib/user.ts around line 117, where the dependency between UserTablePrivileges and the table is configured. Reproduce the deployment with an existing table, then add a new table and its privileges. Done means the new table reaches completion before the grant runs and the deployment no longer fails with the relation-not-found error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100