-
Notifications
You must be signed in to change notification settings - Fork 4k
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
feat(redshift-alpha): directly add parameters to a parameter group or indirectly through a cluster #20944
Conversation
…ParameterGroup or indirectly through a Cluster
…un/aws-cdk into dynamic-redshift-parameter-groups
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a preliminary pass, as there are some things happening that I don't understand in this PR. Can you please add more detail to the PR description?
…o extend ClusterParameterGroupBase
Going off of some of my previous comments I updated the Import class in |
@comcalvi Do you mind re-reviewing this PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New features require a README update. The act of writing the README often helps you assess your approach better and it gives us additional context when reviewing to understand the user experience. Additionally, we generate our documentation from there so it is needed.
I think there are some design issues here and need to be addressed. I also have a lot of questions about what's going on, which tells me that README is especially needed.
@@ -374,6 +393,10 @@ abstract class ClusterBase extends Resource implements ICluster { | |||
targetType: secretsmanager.AttachmentTargetType.REDSHIFT_CLUSTER, | |||
}; | |||
} | |||
|
|||
public addToParameterGroup(_name: string, _value: string): AddParameterResult { | |||
return { parameterAddedResult: AddParameterResultStatus.IMPORTED_RESOURCE_FAILURE }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this just plain return a failure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For addToParameterGroup
in the Cluster
construct, this method should fail for all imported resources since we can't add parameters to them. The L2 Cluster
class is the only class that it wouldn't fail on. Any of the static import methods such as fromClusterAttributes should fail since they are imported resources. In the future there could potentially be more static methods that create imported resources from ClusterBase
which inherit this method but I don't think there would be another instantiated Cluster class that extends ClusterBase
; so I thought the default should be the failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we add parameters to imported Clusters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In CloudFormation, the Cluster is has a property to specify a Parameter Group name . Parameter Groups don't have a property to tie them to a Cluster. That means that the association must be done on the side of the Cluster. I didn't think we could modify imports like that.
Additionally if we could modify imports, we could be potentially overriding an existing association since a Cluster can only have one parameter group associated with it at a time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some things about this approach that I still don't understand. Overall, I agree with @TheRealAmazonKendra. This is getting closer, but still needs some work.
@@ -374,6 +393,10 @@ abstract class ClusterBase extends Resource implements ICluster { | |||
targetType: secretsmanager.AttachmentTargetType.REDSHIFT_CLUSTER, | |||
}; | |||
} | |||
|
|||
public addToParameterGroup(_name: string, _value: string): AddParameterResult { | |||
return { parameterAddedResult: AddParameterResultStatus.IMPORTED_RESOURCE_FAILURE }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we add parameters to imported Clusters?
} else if (this.parameterGroup) { | ||
return this.parameterGroup.addParameter(name, value); | ||
} else { | ||
return { parameterAddedResult: AddParameterResultStatus.IMPORTED_RESOURCE_FAILURE }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please throw errors instead of returning failures. However, I still don't understand why these operations default to failures. What about the resource being imported prevents it from succeeding?
Regardless of why it fails for imported resources, the import should not be considered the default behavior anyway. Imports are the 'special-ish' case.
@@ -22,6 +35,10 @@ abstract class ClusterParameterGroupBase extends Resource implements IClusterPar | |||
* The name of the parameter group | |||
*/ | |||
public abstract readonly clusterParameterGroupName: string; | |||
|
|||
public addParameter(_name: string, _value: string): AddParameterResult { | |||
return { parameterAddedResult: AddParameterResultStatus.IMPORTED_RESOURCE_FAILURE }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. The add operation should not default to failure. Failure should be the exception.
@@ -51,7 +102,7 @@ export class ClusterParameterGroup extends ClusterParameterGroupBase { | |||
* Imports a parameter group | |||
*/ | |||
public static fromClusterParameterGroupName(scope: Construct, id: string, clusterParameterGroupName: string): IClusterParameterGroup { | |||
class Import extends Resource implements IClusterParameterGroup { | |||
class Import extends ClusterParameterGroupBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import may implement the abstract methods, but I don't think we need to change this at this time; this is out-of-scope.
Pull request has been modified.
/** | ||
* Identifier of the cluster | ||
*/ | ||
protected clusterIdentifier: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected clusterIdentifier: string; | |
protected clusterId: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, is this necessary at all? I only see one place where this is used and this.clusterName
could just as easily be used in that place. I'm not seeing the value add.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not needed. I thought that the clusterIdentifier
would make the description in the parameter group a a little nicer.
Given that the cluster
is now a field, it could be taken from that as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use clusterName
instead of creating this new field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That field was removed and replaced with this logic instead. clusterName
could not be used since it caused a circular dependency. (Parameter group description field containing a ref
to the Cluster, Cluster's group name field containing a ref
to the Parameter Group).
|
||
if (secret) { | ||
this.secret = secret.attach(this); | ||
} | ||
|
||
const defaultPort = ec2.Port.tcp(this.clusterEndpoint.port); | ||
this.connections = new ec2.Connections({ securityGroups, defaultPort }); | ||
this.clusterIdentifier = props.clusterName ?? Names.uniqueResourceName(this, {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clusterName here would never be undefined
because it's being set to the ref.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a case of poorly named variables. props.clusterName
!= this.clusterName
. The clusterName prop is either a string
or undefined
and is being used as the CfnCluster
's clusterIdentifier property
Co-authored-by: Kendra Neil <[email protected]>
Pull request has been modified.
@Mergifyio update |
✅ Branch has been successfully updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the integ tests still need to be updated with the output from the suggested changes.
Pull request has been modified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some requested changes still not addressed.
I believe they have been addressed, the comments look to be on outdated code |
Pull request has been modified.
@TheRealAmazonKendra Can you re-review this? I believe I've addressed the requested changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all your work on this! I have several comments below.
Apologies for not thinking about the ability to add multiple parameters at a time in a previous revision, but I'm thinking that if it's a use case that seem likely, going that direction would be significantly better.
```ts fixture=cluster | ||
cluster.addToParameterGroup('enable_user_activity_logging', 'true'); | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't rendering correctly. I suspect that the issue is the fixture=cluster
piece causing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll fix it for the example in this PR and raise an issue. Looking at the documentation it's also not rendering for the other examples using fixture=cluster
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I think none of the fixtures (even the default) are loading properly for the redshift alpha library
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const param: { [name: string]: string } = {}; | ||
param[name] = value; | ||
this.parameterGroup = new ClusterParameterGroup(this, 'ParameterGroup', { | ||
description: `Parameter Group for the ${this.cluster.clusterIdentifier ?? Names.uniqueResourceName(this, {})} Redshift cluster`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think now that you are using this.cluster.clusterIdentifier
, Names.uniqueResourceId
is no longer needed in this context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The clusterIdentifier can be undefined. It's being set to the optional clusterName prop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that happens before this.clusterName
is set to this.cluster.ref
.
I think that I suggested using Names.uniqueResourceName
instead of Names.uniqueResourceId
somewhere in here, but since it wasn't used there, it doesn't make sense to use it here. It won't be named that and we'd be giving false information.
You can set
clusterIdentifier: props.clusterName ?? Names.uniqueResourceName(this), {
maxLength: 63,
separator: '-',
allowedSpecialCharacters: '-',
}
up on line 528. That would work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with the false information.
It looks like the cluster Identifier needs to be unique account wide. So instead of setting the name to with Names.uniqueResourceName
I think it might be better to fall back to the paramter group default description if the identifier isn't provided
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the Names.uniqueResourceName
and falling back to the default
@@ -32,6 +32,8 @@ const cluster = new redshift.Cluster(stack, 'Cluster', { | |||
encryptionKey: new kms.Key(stack, 'custom-kms-key'), | |||
}); | |||
|
|||
cluster.addToParameterGroup('enable_user_activity_logging', 'true'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see more test cases. One where the parameters are added directly in the constructor and one where addParameter() is used. Or rather, addParameters() if you take my suggestion above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add some more tests to the cluster.test.ts
for this. I don't think we need to update the integration test for this (unless we do change to addParameters()
)
Co-authored-by: Kendra Neil <[email protected]>
Pull request has been modified.
this.parameters[name] = value; | ||
this.resource.parameters = this.parseParameters(); | ||
} else if (existingValue !== value) { | ||
throw new Error(`The parameter group already contains the parameter "${name}", but with a different value (Given: ${value}, Existing: ${existingValue}).`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add the name of the parameter group in here in case the user has an app with multiple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameter groups don't have names, but I agree that it makes sense to identify it somehow , so maybe it makes sense to use Names.uniqueResourceName
here
throw new Error(`The parameter group id "${Names.uniqueResourceName(this, {})}" already contains the parameter "${name}", but with a different value (Given: ${value}, Existing: ${existingValue}).`);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my most recent comment below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case it's set to the Instrinsic Ref
of CfnClusterParameterGroup
, so the error message would contain a Token
.
Considering that this is runtime error, I think using Names.uniqueResourceName
(along with the stack trace) should be helpful enough to locate the problematic parameter group
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be providing the customer with inaccurate information. Sure, it's an approximation, but it's not actually the name of the resource. I suppose the stack trace will have to provide enough information in conjunction with the key value pair they're trying to add.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted back to this message in the latest commit
const param: { [name: string]: string } = {}; | ||
param[name] = value; | ||
this.parameterGroup = new ClusterParameterGroup(this, 'ParameterGroup', { | ||
description: `Parameter Group for the ${this.cluster.clusterIdentifier ?? Names.uniqueResourceName(this, {})} Redshift cluster`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that happens before this.clusterName
is set to this.cluster.ref
.
I think that I suggested using Names.uniqueResourceName
instead of Names.uniqueResourceId
somewhere in here, but since it wasn't used there, it doesn't make sense to use it here. It won't be named that and we'd be giving false information.
You can set
clusterIdentifier: props.clusterName ?? Names.uniqueResourceName(this), {
maxLength: 63,
separator: '-',
allowedSpecialCharacters: '-',
}
up on line 528. That would work.
@@ -62,17 +63,46 @@ export class ClusterParameterGroup extends ClusterParameterGroupBase { | |||
*/ | |||
public readonly clusterParameterGroupName: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't a parameter group name?
Pull request has been modified.
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
… indirectly through a cluster (aws#20944) Closes [aws#20656](aws#20656) This PR enables users to directly add parameters to a `ClusterParameterGroup` or indirectly through a `Cluster`. There are a few reasons why this would not succeed, such as the parameter already existing or trying to add parameters to an Imported Parameter Group and/or Cluster. With this in mind, the methods return a `AddParameterResultStatus` which let's developers handle failure cases more elegantly. Ex. On `SUCCESS` or `SAME_VALUE_FAILURE` do nothing, but on `CONFLICTING_VALUE_FAILURE` or `IMPORTED_RESOURCE_FAILURE` throw some sort of error indicating what you need the developer to do in their application to resolve the issue. This is very useful in the case of vending constructs that take in a Redshift Cluster as an input. See aws#20656 for more context. I don't think this is significant enough to be called out in the README with an example, but happy to add one if necessary. ---- ### All Submissions: * [X] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [X] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [X] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Closes #20656
This PR enables users to directly add parameters to a
ClusterParameterGroup
or indirectly through aCluster
. There are a few reasons why this would not succeed, such as the parameter already existing or trying to add parameters to an Imported Parameter Group and/or Cluster. With this in mind, the methods return aAddParameterResultStatus
which let's developers handle failure cases more elegantly.Ex. On
SUCCESS
orSAME_VALUE_FAILURE
do nothing, but onCONFLICTING_VALUE_FAILURE
orIMPORTED_RESOURCE_FAILURE
throw some sort of error indicating what you need the developer to do in their application to resolve the issue.This is very useful in the case of vending constructs that take in a Redshift Cluster as an input. See #20656 for more context.
I don't think this is significant enough to be called out in the README with an example, but happy to add one if necessary.
All Submissions:
Adding new Unconventional Dependencies:
New Features
yarn integ
to deploy the infrastructure and generate the snapshot (i.e.yarn integ
without--dry-run
)?By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license