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

"import" is a reserved word in Java #89

Closed
eladb opened this issue Jun 13, 2018 · 20 comments · Fixed by #2456
Closed

"import" is a reserved word in Java #89

eladb opened this issue Jun 13, 2018 · 20 comments · Fixed by #2456
Assignees
Labels
effort/medium Medium work item – several days of effort package/awscl Cross-cutting issues related to the AWS Construct Library pr/breaking-change This PR is a breaking change. It needs to be modified to be allowed in the current major version.

Comments

@eladb
Copy link
Contributor

eladb commented Jun 13, 2018

All AWS constructs have a static import method to allow bringing-in resources defined externally. However, import is reserved in Java (and possibly in other languages).

In the interim the jsii compiler will simply add an _ at the end of the method name, but we need to find a new name for the method and rename across the codebase.

@rix0rrr
Copy link
Contributor

rix0rrr commented Jun 13, 2018

I think we shouldn't need to export/import anyway, see cross-stack references design

@eladb
Copy link
Contributor Author

eladb commented Jun 13, 2018

That's one way to address this problem 😄

@eladb
Copy link
Contributor Author

eladb commented Sep 17, 2018

That's something we should probably do before 1.0

@eladb eladb added pr/breaking-change This PR is a breaking change. It needs to be modified to be allowed in the current major version. package/awscl Cross-cutting issues related to the AWS Construct Library labels Dec 17, 2018
@rix0rrr
Copy link
Contributor

rix0rrr commented Jan 8, 2019

Yeah we do need to export()/import() for cross-app references.

@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

Also, we should standardize the naming for importFromContext (which I argued should be importFromEnvironment).

@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

Okay, here's a proposal (following an online discussion with @RomainMuller and @rix0rrr). We'll use Bucket as an example:

interface BucketAttributes {
  readonly bucketArn: string;
  readonly bucketName: string;
}

// mixing data types and interfaces?? would that be okay?
interface IBucket extends BucketAttributes {
  export(): BucketAttributes;
}

class Bucket {
  public static fromAttributes(parent: Construct, id: string, attributes: BucketAttributes): IBucket;

  // if you only have a bucket ARN we can provide a convenience method which parses the
  // bucket name from the ARN and vice versa
  public static fromArn(parent: Construct, id: string, bucketArn: string): IBucket;
  public static fromBucketName(parent: Construct, id: string, bucketName: string): IBucket;
}

The only problem here is that we are mixing interfaces and data types (IBucket extends BucketAttributes). I am not 100% sure that's an issue (see aws/jsii#271, aws/jsii#265). @rix0rrr thoughts?

@rix0rrr
Copy link
Contributor

rix0rrr commented Jan 8, 2019

I don't think the interface inheritance is going to be an issue.

On the other hand, not convinced the combination of FooAttributes Foo.fromAttributes() and IFoo extends FooAttributes is going to work for more than the trivial resource types.

Also seems like the fromArn and fromBucketName could have been subsumed by fromAttributes() with optional parameters and runtime checking. We do this in many other cases, I'm not sure why this warrants top-level functions all of a sudden.

All's I'm saying is that I don't think we gain anything by tying FooAttributes so tightly to IFoo, except limiting our own freedom of movement.

@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

I am feeling uneasy about the runtime checks we have around imports. It’s a bit of ugliness I’d love to get rid of. It also occasionally violate the rule that says that if all properties are optional then “props” should also be optional.

The reason I feel this tie in makes sense is because there is a strong correlation between “import props” (for lack of a better term at the moment) and the set of attributes intrinsically available for a resource. I don’t like the fact that today we literally have to duplicate this set between BucketImportProps and IBucket, only with different levels of optionality.

The “fromAttributes” method (with everything non-optional) will be useful espeically for exports and the various fromXxx methods will be more useful when you have a specific attribute value such as an ARN, etc. I like the fact that this approach gives us the ability to express the various import use cases without sacrificing type safety (contrary to the runtime checks approach).

@RomainMuller
Copy link
Contributor

I agree with @eladb's point on the optionals issue. Since JSII can't allow "all type unions", the separate methods are the only way to restore type safety while allowing possibly disjoint sets of required/optional fields.

@rix0rrr
Copy link
Contributor

rix0rrr commented Jan 8, 2019

I don’t like the fact that today we literally have to duplicate this set between BucketImportProps and IBucket, only with different levels of optionality.

The argument against DRY is that some things may look the same in some cases, but they're actually not the same, and now you've introduced coupling that shouldn't be there.

I think S3 is a poor use case here. If you can make this design work in the ELBv2 package and/or the ECS package, then I withdraw my objections.

@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

@rix0rrr fair enough. Will definitely try to see how it plays out in those cases.

@eladb eladb self-assigned this Jan 8, 2019
@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

Okay, @rix0rrr was right. Having IXxx extend XxxAttributes doesn't really make sense for more complex resources that "bundle" other resources when they are exported.

For example, when you export a VPC, you export the set of public and private subnet IDs. This means that the output of export() looks like this:

  vpcId: string;
  availabilityZones: string[];
  publicSubnetIds?: string[];
  publicSubnetNames?: string[];
  privateSubnetIds?: string[];
  privateSubnetNames?: string[];
  isolatedSubnetIds?: string[];
  isolatedSubnetNames?: string[];

But in IVpcNetwork, these should be strongly typed:

  readonly vpcId: string;
  readonly publicSubnets: IVpcSubnet[];
  readonly privateSubnets: IVpcSubnet[];
  readonly isolatedSubnets: IVpcSubnet[];
  readonly availabilityZones: string[];

So, no! IVpcNetwork shouldn't extend VpcNetworkAttributes (or whatever we call it).

@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

So, I think VpcNetworkAttributes doesn't make sense as the name for the output of export (and input of import).

Here's a merge between @rix0rrr's original idea and the fromXxx idea:

interface BucketExport {
  bucketArn: string;
  bucketName: string;
}

class Bucket {
  public static fromExport(scope: cdk.Construct, id: string, export: BucketExport): IBucket;
  public static fromBucketArn(scope: cdk.Construct, id: string, bucketArn: string): IBucket;
  public static fromBucketName(scope: cdk.Construct, id: string, bucketName: string): IBucket;
}

interface IBucket {
  bucketArn: string;

  export(): BucketExport;
}

Thoughts?

@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

And we can create some awslint rules that will encourage/enforce fromXxx to be defined. For example, if there's a single attribute we can require that fromThatAttribute will be defined. If there is an ARN attribute, we can require that fromXxxArn will be defined, etc.

@sam-goodwin
Copy link
Contributor

I think being explicit like this is right; it's intuitive/self-descriptive and has no chance of colliding with reserved words in any language.

How does fromExport and BucketExport look after cross-stack references are automated?

@rix0rrr
Copy link
Contributor

rix0rrr commented Jan 8, 2019

I am okay with the proposed keywords; but I think our cross-stack export mechanism needs some thinking. We have to carry over a bunch of data, and there is no convenient serialization mechanism we can use

@rix0rrr
Copy link
Contributor

rix0rrr commented Jan 8, 2019

I tend towards a structured set of exports keyed off an identifier string

@eladb
Copy link
Contributor Author

eladb commented Jan 8, 2019

That’s a good point Sam. I guess that we would only need “fromXxx” when cross stack references are implicit. @rix0rrr?

@eladb
Copy link
Contributor Author

eladb commented Jan 9, 2019

@sam-goodwin brought up a good point. We need to revisit imports/exports altogether given #1436. I will submit an PR with an RFC and will take the opportunity to resolve this as well.

@fulghum fulghum added the effort/medium Medium work item – several days of effort label Jan 10, 2019
@eladb eladb added @aws-cdk/core Related to core CDK functionality and removed @aws-cdk/core Related to core CDK functionality labels Mar 4, 2019
@eladb
Copy link
Contributor Author

eladb commented Apr 15, 2019

Superseded by #2273

eladb pushed a commit that referenced this issue May 6, 2019
Implement and apply the following awslint rules:

- `awslint:from-method`: resources should have at least one static "from" method
- `awslint:from-signature`: enforce method signature
- `awslint:from-attributes`: a `fromAttributes` static method can be used to import from more than a single attribute
- `awslint:from-attributes-struct`: `fromFooAttributes` should accept a `FooAttributes` struct as input
- `awslint:no-static-import`: forbids a static `import` (deprecation helper rule)
- `awslint:attribute-tag`: all resource attributes should have an "@Attribute" doc tag
- `awslint:attribute-readonly`: all attributes must be readonly properties

Many resources now have an additional `fromFooArn` or `fromFooName` for importing from the intrinsic attribute.

Misc:
- Deprecate `Token.unresolved` in favor of `Token.isToken` (more idiomatic).
- Added eager resolution of `Fn.select` and `Fn.split` in case they receive concrete values
- Refactoring of awslint (decouple "resource" from "cfn-resource").
- Added `iam.Grant.drop` which allows "dropping" a grant on the floor for imported resources

NOTE: many of the new methods do not have inline documentation. We will address this in a subsequent pass that will be focused on docs.

Fixes #2450 
Fixes #2428 
Fixes #2424
Fixes #2429 
Fixes #2425
Fixes #2422
Fixes #2423
Fixes #89

BREAKING CHANGE: all `Foo.import` static methods are now `Foo.fromFooAttributes`
* All `FooImportProps` structs are now called `FooAttributes`
* `stepfunctions.StateMachine.export` has been removed.
* `ses.ReceiptRule.name` is now `ses.ReceiptRule.receiptRuleName`
* `ses.ReceiptRuleSet.name` is now `ses.ReceiptRuleSet.receiptRuleSetName`
* `secretsmanager.AttachedSecret` is now called `secretsmanager.SecretTargetAttachment` to match service semantics
* `ecr.Repository.export` has been removed
* `s3.Bucket.bucketUrl` is now called `s3.Bucket.bucketWebsiteUrl`
* `lambda.Version.functionVersion` is now called `lambda.Version.version`
* `ec2.SecurityGroup.groupName` is now `ec2.SecurityGroup.securityGroupName`
* `cognito.UserPoolClient.clientId` is now `cognito.UserPoolClient.userPoolClientId`
* `apigateway.IRestApiResource` is now `apigateway.IResource`
* `apigateway.IResource.resourcePath` is now `apigateway.IResource.path`
* `apigateway.IResource.resourceApi` is now `apigateway.IResource.restApi`
SanderKnape pushed a commit to SanderKnape/aws-cdk that referenced this issue May 14, 2019
Implement and apply the following awslint rules:

- `awslint:from-method`: resources should have at least one static "from" method
- `awslint:from-signature`: enforce method signature
- `awslint:from-attributes`: a `fromAttributes` static method can be used to import from more than a single attribute
- `awslint:from-attributes-struct`: `fromFooAttributes` should accept a `FooAttributes` struct as input
- `awslint:no-static-import`: forbids a static `import` (deprecation helper rule)
- `awslint:attribute-tag`: all resource attributes should have an "@Attribute" doc tag
- `awslint:attribute-readonly`: all attributes must be readonly properties

Many resources now have an additional `fromFooArn` or `fromFooName` for importing from the intrinsic attribute.

Misc:
- Deprecate `Token.unresolved` in favor of `Token.isToken` (more idiomatic).
- Added eager resolution of `Fn.select` and `Fn.split` in case they receive concrete values
- Refactoring of awslint (decouple "resource" from "cfn-resource").
- Added `iam.Grant.drop` which allows "dropping" a grant on the floor for imported resources

NOTE: many of the new methods do not have inline documentation. We will address this in a subsequent pass that will be focused on docs.

Fixes aws#2450 
Fixes aws#2428 
Fixes aws#2424
Fixes aws#2429 
Fixes aws#2425
Fixes aws#2422
Fixes aws#2423
Fixes aws#89

BREAKING CHANGE: all `Foo.import` static methods are now `Foo.fromFooAttributes`
* All `FooImportProps` structs are now called `FooAttributes`
* `stepfunctions.StateMachine.export` has been removed.
* `ses.ReceiptRule.name` is now `ses.ReceiptRule.receiptRuleName`
* `ses.ReceiptRuleSet.name` is now `ses.ReceiptRuleSet.receiptRuleSetName`
* `secretsmanager.AttachedSecret` is now called `secretsmanager.SecretTargetAttachment` to match service semantics
* `ecr.Repository.export` has been removed
* `s3.Bucket.bucketUrl` is now called `s3.Bucket.bucketWebsiteUrl`
* `lambda.Version.functionVersion` is now called `lambda.Version.version`
* `ec2.SecurityGroup.groupName` is now `ec2.SecurityGroup.securityGroupName`
* `cognito.UserPoolClient.clientId` is now `cognito.UserPoolClient.userPoolClientId`
* `apigateway.IRestApiResource` is now `apigateway.IResource`
* `apigateway.IResource.resourcePath` is now `apigateway.IResource.path`
* `apigateway.IResource.resourceApi` is now `apigateway.IResource.restApi`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort/medium Medium work item – several days of effort package/awscl Cross-cutting issues related to the AWS Construct Library pr/breaking-change This PR is a breaking change. It needs to be modified to be allowed in the current major version.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants