-
Notifications
You must be signed in to change notification settings - Fork 83
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
rfc 328 - polyglot assert #330
Conversation
afb91fa
to
aad9ed4
Compare
2b886b7
to
171f267
Compare
171f267
to
2a3c9e0
Compare
text/0328-polyglot-assert.md
Outdated
template. | ||
|
||
```ts | ||
inspect.assertMatchTemplateBeta1({ |
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 assert
everywhere seems a little redundant? Especially if we rename the inspect
variable assert
. How about:
inspect.assertMatchTemplateBeta1({ | |
assert.matchTemplateBeta1({ |
(And same for assert.hasResourceBeta1
etc)
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.
Adding the assert
prefix makes it clear that these methods will throw if the conditions are not met.
I've left space, for the future, to add a matchTemplate()
that returns true/false. Maybe premature(?).
text/0328-polyglot-assert.md
Outdated
Properties: { Foo: 'Bar' }, | ||
DependsOn: [ 'Waldo', 'Fred' ], | ||
}, { | ||
part: ResourcePartBeta1.COMPLETE_BETA1, |
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.
Again, no need to add _BETA1 everywhere. It's sufficient that the top level type has that prefix...
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 say I wanted to change the behaviour of this enum value. With your suggestion I would need to create a new enum ResourcePartBeta2
and then create new methods with Beta2
(or whatever) suffix everywhere this enum is used.
More pragmatic to keep the suffix, no?
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 am not sure I can think of a reason you'd want to change the value of the enum member. It's normally not even needed to specify a value.
We should be consistent about these suffixes. If the entire type is "Beta", I don't see any value in actually polluting all the members with that suffix.
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.
To @nija-at point, if we only use betaX
on the containing type (e.g class), what do we do when we want to deprecate an internal member? For example, assume the autoScalingGroup
class is in preview phase, and we only want to change the behavior of formAutScalingGroupName
method, do we need to deprecate the entire autoScalingGroup
class for that?
export class AutoScalingGroupBeta {
public static fromAutoScalingGroupName(scope: Construct, id: string, autoScalingGroupName: string):
.....
}
}
My gut feeling is that it will be less ideal from a user experience perspective.
there are a lot of nuance here, I think we need to flush out the preview specification so we can be consistent across the code base.
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 would just deprecate AutoScalingGroupBeta
, and introduce AutoScalingGroupBeta2
with this new method, while proxying all the deprecated methods from the deprecated type to the new type.
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.
How will this work for users consuming fromAutoScalingGroupName
? If you proxy it, you will be introducing a breaking change for users of AutoScalingGroupBeta
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.
Good callout. Of course this specific method will not be proxied as-is in order to preserve the legacy behavior in the deprecated class.
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.
Agree with Elad here. Having to call fromAutoScalingGroupName()
AutoScalingGroupBeta1.fromAutoScalingGroupNameBeta1()
on the off-chance we will want to deprecate it seems like the wrong tradeoff to me.
Also, let's assume for a second we do go down this route, and call it AutoScalingGroupBeta1.fromAutoScalingGroupNameBeta1()
. What do we call the replacement method then? AutoScalingGroupBeta1.fromAutoScalingGroupNameBeta2()
? That looks pretty bad...
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 we are over indexing on how things look. Our main objective is to make sure it is clear that an API is in preview. The second objective is to make is easy for users to use preview APIs, will introducing a whole new class will make it harder for users to upgrade? It can be, as the class usage is more prevalent than a single method in a user application (more references to the AutoScalingGroup
class in the code base than to fromAutoScalingGroupName
).
I think we need to make this decision in a dedicated PR, try out a few use cases and flush out the details using code samples.
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.
My two cents. In general, looks really good.
The import statement you will need to use is - | ||
|
||
```ts | ||
import { assertions } from 'aws-cdk-lib'; |
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.
Really? We're adding a testing library to aws-cdk-lib
? This seems like a mistake to me...
Is this decision final?
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 RFC is about making this decision.
Why is it a mistake to add a testing library to aws-cdk-lib
?
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.
@skinny85 what's your arguments against making the assertion library part of the AWS CDK. It's a common practice to include assertion utilities in standard libraries (see node.js's 'assert' for example).
We want to standardize test assertions to be an intrinsic part of the AWS CDK so it can be used as a foundation for the ecosystem.
The important side effect is that it including it in the AWS CDK itself will allow us to use it from within the AWS CDK codebase, even if/when we aws-cdk-lib becomes a truly monolithic codebase (after we stop supporting v1).
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.
Do we have any concerns around the size of the CDK package? If so, this could be an argument against including assertions in the main package, which would force users to deploy a testing library to a production environment, where it's not used. I know with Javascript we can use things like webpack, but I'm not sure whether this can be done in other languages. Then again, depending on the additional size, this may not even be relevant.
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 do have concerns around the size but the assertion library is negligible comparing to the two huge lambda layers we bundle into the library, which is where we should optimize (see here).
Given this and working backwards from the key requirement, the new assert module | ||
must be part of the AWS CDK monorepo. |
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 logic doesn't convince me.
Why can't this be a separate module that depends on aws-cdk-lib
?
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.
How would you satisfy the requirement I've identified (in the above section) if this is a separate module?
Do you disagree with that requirement?
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 can ship a separate experimental assert library from a module in the monorepo, re-writing it as needed at build time.
Same way as we re-write the stable modules today to package them as part of monocdk, and the same way as we plan to ship the existing experimental modules like @aws-cdk/aws-appmesh
(which has version 1.107.0
) as new modules @aws-cdk-lib-experiments/aws-appmesh
(with version 0.1.0
).
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 point you again towards the requirements section and quote it here, because your reply seems to ignore it -
The key requirement for the design choices is dogfooding.
The new assert APIs must be usable from within the AWS CDK, and over time,
all CDK modules that use the old assert module should be migrated to the new one.
If we ship this as an experimental module, I believe we cannot take declare a dependency on it from any of our stable modules.
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.
If we ship this as an experimental module, I believe we cannot take declare a dependency on it from any of our stable modules.
Pretty sure we can, because it will be a devDependency
.
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 deal with all this complexity? If we just publish this as any CDK construct library, it keeps things simple and gets the job done. We can deal with it the same way we handle everything else.
Why do you not like shipping this as any other module? The only difference I see is that these does not participate in synthesis, which is acceptable.
Because it bloats the aws-cdk-lib
module with test code, and forces you to use the ugly Beta1
names.
I honestly don't see the problem here. We will have a module in the monorepo, @aws-cdk/assertions
or something, which the single (v1) modules will depend on. This takes care of dogfooding. Then we re-package the module to be released with whatever name we want, @aws-cdk-lib/assertions
or something else, in version 0.x.y
. It will peerDepend
on aws-cdk-lib
.
This is exactly the process we want to have for other experimental modules.
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.
Ok. Thanks for the feedback.
I'll take that into consideration before my final decision.
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.
@skinny85 I am not sure I understand your arguments against including this is the standard library (besides module size, which is not a very strong argument given this is likely to add a few KiBs).
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.
It also allows us to skip the ugly Beta1
suffixes.
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's a fair argument.
If we can release this library as an experimental module without adding any further complexity, we can do so.
However, after graduating to stable, the module will be included in aws-cdk-lib
(just like any other experimental module).
94dfb1d
to
4ebf3bb
Compare
text/0328-polyglot-assert.md
Outdated
|
||
```py | ||
# In Python | ||
assertion.assertResourceCountIs('Foo::Bar', 2) |
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.
assertion.assertResourceCountIs('Foo::Bar', 2) | |
assertion.assert_resource_count_is('Foo::Bar', 2) |
text/0328-polyglot-assert.md
Outdated
"Qux": [ "Waldo", "Fred" ], | ||
} """; | ||
|
||
assertion.assertHasResource('Foo::Bar', json.loads(expected)) |
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.
underscore
new AssertResourceOptionsBeta1.Builder().part(ResourcePartBeta1.COMPLETE).build()); | ||
``` | ||
|
||
```py |
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 have to say that I feel the multi language readme is a bit too much. I don't see why this RFC is any different than any README/RFC we have written so far in which we write the typescript story and have JSII map it to other languages.
Just makes it harder from a reader's perspective to focus on the important things, which are the assertions API.
This is not a JSII RFC...
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.
Generally, I agree with you.
The part I want to emphasize in the RFC is that, for the best ergonomics in non-javascript languages, users will have to use a separate 3p library to convert to dict
in Python and Map
in Java, etc.
My examples show the use in Gson
(for Java) and json
(for Python).
Calling out that experience is important.
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.
Because of the other languages, should we consider a string-based API as well? To avoid all of that low-level stuff with Gson
/ json
?
// in Java
assert.assertTemplateMatchesString("""{
"Resources": {
"Type": "Foo::Bar",
"Properties": {
"Baz": false
}
}
}""");
# in Python
assertion.assert_template_matches_string("""{
"Resources": {
"Type": "Foo::Bar",
"Properties": {
"Baz": false
}
}
}""")
Thoughts?
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.
Feels like we can add that later
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.
Definitely a nice idea that we can add as the library evolves.
| Language | Pkg Manager | Package | | ||
| --------------------- | ------------|---------------------------------------------- | | ||
| typescript/javascript | npm | `@aws-cdk/assertions` | | ||
| Java | Maven | `software.amazon.awscdk.assertions` | |
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.
overkill
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?
Isn't it a valid FAQ that users would expect to see? especially given that, the primary value prop of this RFC is that the module is available in all languages.
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.
Of course it is but just feels like it's a detail we don't have to expand on in the RFC since it's derived from the submodule name and there isn't any control here.
The import statement you will need to use is - | ||
|
||
```ts | ||
import { assertions } from 'aws-cdk-lib'; |
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.
@skinny85 what's your arguments against making the assertion library part of the AWS CDK. It's a common practice to include assertion utilities in standard libraries (see node.js's 'assert' for example).
We want to standardize test assertions to be an intrinsic part of the AWS CDK so it can be used as a foundation for the ecosystem.
The important side effect is that it including it in the AWS CDK itself will allow us to use it from within the AWS CDK codebase, even if/when we aws-cdk-lib becomes a truly monolithic codebase (after we stop supporting v1).
Given this and working backwards from the key requirement, the new assert module | ||
must be part of the AWS CDK monorepo. |
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.
@skinny85 I am not sure I understand your arguments against including this is the standard library (besides module size, which is not a very strong argument given this is likely to add a few KiBs).
LGTM approved as far as I am concerned |
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.
LGTM.
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache-2.0 license