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

feat(efs): create EFS file systems #6373

Merged
merged 11 commits into from
Mar 5, 2020
Merged

Conversation

yashda
Copy link

@yashda yashda commented Feb 19, 2020

  • 100% unit test coverage.
  • This was tested by creating an EFS using this construct in a cdk application.
    A instance was also created in this app, which successfully mounted it.
import {
    AmazonLinuxGeneration,
    AmazonLinuxImage,
    Instance,
    InstanceClass,
    InstanceSize,
    InstanceType,
    SubnetType,
    Vpc
} from '@aws-cdk/aws-ec2';
import * as efs from '@aws-cdk/aws-efs';
import * as cdk from '@aws-cdk/core';

export class TestEfscdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        // The code that defines your stack goes here

        const vpc = Vpc.fromLookup(this, 'VPC', {
          isDefault: true
        });

        const fileSystem = new efs.EfsFileSystem(this, 'EfsFileSystem', {
            vpc,
            encrypted: true,
            fileSystemTags: [new cdk.Tag("key1", "value1")],
            lifecyclePolicy: efs.EfsLifecyclePolicyProperty.AFTER_14_DAYS,
            performanceMode: efs.EfsPerformanceMode.GENERAL_PURPOSE,
            throughputMode: efs.EfsThroughputMode.BURSTING
        });

        const inst = new Instance(this, 'inst', {
            instanceType: InstanceType.of(InstanceClass.T2, InstanceSize.LARGE),
            machineImage: new AmazonLinuxImage({
                generation: AmazonLinuxGeneration.AMAZON_LINUX_2
            }),
            vpc,
            vpcSubnets: {
                subnetType: SubnetType.PUBLIC,
            },
        });

        fileSystem.connections.allowDefaultPortFrom(inst);

        inst.userData.addCommands("yum check-update -y",
            "yum upgrade -y",
            "apt-get -y update",
            "apt-get -y upgrade",
            "yum install -y amazon-efs-utils",
            "apt-get -y install amazon-efs-utils",
            "yum install -y nfs-utils",
            "apt-get -y install nfs-common",
            "file_system_id_1=" + fileSystem.fileSystemID,
            "efs_mount_point_1=/mnt/efs/fs1",
            "mkdir -p \"${efs_mount_point_1}\"",
            "test -f \"/sbin/mount.efs\" && echo \"${file_system_id_1}:/ ${efs_mount_point_1} efs defaults,_netdev\" >> /etc/fstab || " +
            "echo \"${file_system_id_1}.efs." + cdk.Stack.of(this).region + ".amazonaws.com:/ ${efs_mount_point_1} nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev 0 0\" >> /etc/fstab",
            "mount -a -t efs,nfs4 defaults");
  }
}

closes #6286


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

* 100% unit test coverage.
* This was tested by creating an EFS using this construct in a cdk application.
  A instance was also created in this app, which successfully mounted it.

closes aws#6286
@yashda yashda requested a review from rix0rrr February 19, 2020 20:31
/**
* Interface to implement AWS File Systems.
*/
export interface IFileSystem extends IResource, ec2.IConnectable {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention of adding this interface is to have a common interface for all AWS file systems (FSx windows, lustre). This can be moved to aws-core once we have construct for another type of file system.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, don't do this yet. Just make this an IEfsFileSystem interface. We can always add the superinterface later if necessary, and they should probably have different names in any case.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 9b208a6
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@pahud
Copy link
Contributor

pahud commented Feb 20, 2020

@yashda Good job!

One question - Any tools to help you with 100% unit test coverage?

I have been working on my recent PR for cloud9 L2 but can't have enough coverage. Any advice would be highly appreciated.

@yashda
Copy link
Author

yashda commented Feb 20, 2020

@yashda Good job!

One question - Any tools to help you with 100% unit test coverage?

I have been working on my recent PR for cloud9 L2 but can't have enough coverage. Any advice would be highly appreciated.

@pahud istanbul is already integrated with CDK, so whenever you run unit tests, it generates the coverage report at path aws-cdk\packages\@aws-cdk\aws-<module>\coverage. All the statements, branches and lines which are not covered in the UTs can be seen highlighted in index.html. Based on this report, more tests can be added to the code to increase coverage.
Does that answers your question?


const myVpc = new ec2.Vpc(this, 'VPC');
const fileSystem = new efs.EfsFileSystem(this, 'MyEfsFileSystem', {
vpc: myVpc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something very trivial, but can you make sure to change indentation to 2 spaces everywhere?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example still shows up as 4 spaces for me.

packages/@aws-cdk/aws-efs/README.md Show resolved Hide resolved
*
* @default - no tags will be added
*/
readonly fileSystemTags?: Tag[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagging is done centrally (https://docs.aws.amazon.com/cdk/latest/guide/tagging.html) so doesn't need to be added here.

/**
* Interface to implement AWS File Systems.
*/
export interface IFileSystem extends IResource, ec2.IConnectable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, don't do this yet. Just make this an IEfsFileSystem interface. We can always add the superinterface later if necessary, and they should probably have different names in any case.

*
* @attribute
*/
readonly fileSystemID: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Id. This will be come file_system_i_d in Python.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.

/**
* Import an existing File System from the given properties.
*/
public static fromEfsFileSystemAttributes(scope: Construct, id: string, attrs: EfsFileSystemAttributes): IFileSystem {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can a filesystem imported in this way still be mounted? What would that look like?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mount script in the user data just needs the file systems Id, which we are setting in the object here. We additionally need to update the connections to allow connection for a different resource.
Since we are setting both these properties here while importing an existing file system, it will be mounted using the same same way.

packages/@aws-cdk/aws-efs/lib/efs-file-system.ts Outdated Show resolved Hide resolved
packages/@aws-cdk/aws-efs/lib/file-system.ts Outdated Show resolved Hide resolved
/**
* EFS Lifecycle Policy, if a file is not accessed for given days, it will move to EFS Infrequent Access.
*
* @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html#cfn-efs-filesystem-performancemode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong link.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

*/
export enum EfsLifecyclePolicyProperty {
/**
* After 7 days of inaccessibility.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not "inaccessibility", but "not being accessed"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@mergify mergify bot dismissed rix0rrr’s stale review February 27, 2020 19:51

Pull request has been modified.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 188fec0
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

* 100% unit test coverage.
* This was tested by creating an EFS using this construct in a cdk application.
  A instance was also created in this app, which successfully mounted it.

closes aws#6286
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 6d080bc
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: b78a698
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@rix0rrr
Copy link
Contributor

rix0rrr commented Mar 2, 2020

(Regular-merging master back to get rid of unrelated changes)

rix0rrr
rix0rrr previously requested changes Mar 2, 2020

const myVpc = new ec2.Vpc(this, 'VPC');
const fileSystem = new efs.EfsFileSystem(this, 'MyEfsFileSystem', {
vpc: myVpc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example still shows up as 4 spaces for me.

},
});

inst.userData.addCommands("yum check-update -y",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like putting in commands that will fail on one of the platforms and then silently ignoring the errors. Be prepared for UserData scripts to be executed under bash -e.

In the example you are creating an Amazon Linux instance, so no real need to add the Ubuntu commands though. If you want to show the commands for multiple platforms (admirable) then show the difference in comments:

inst.userData.addCommands(
  'yum check-update -y',  // Ubuntu: apt-get -y update
   ...);

Also this example is incomplete, it doesn't show creation of the EFS filesystem and how to allow connections.

"apt-get -y install amazon-efs-utils",
"yum install -y nfs-utils",
"apt-get -y install nfs-common",
"file_system_id_1=" + fileSystem.fileSystemID,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to fileSystemId if I'm not mistaken.

/**
* Interface to implement AWS File Systems.
*/
export interface IEfsFileSystem extends IResource, ec2.IConnectable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, IResource doesn't need to be in here. Sorry missed that on the first go-around.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my understanding, why don't we need this interface to be implemented here? I believe that the file system act as a cloud formation resource.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I figured that we are already extending Resource which implements IResource.

}
}

this.efsFileSystem = new CfnFileSystem(this, "FileSystem", {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Construct id must be "Resource".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

subnetId
});
this.mountTargets.push(efsMountTarget);
this.mountTargetIdentifiers.push(efsMountTarget.ref);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we're now holding on to even more attributes of the mount targets, but why would you need these?

The UserData script you gave uses only the ID and nothing else. Why do we need the IDs and IP addresses?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file system can be mounted using the IP addresses as well. The UserData in the example creates the domain name from file system and uses it for mounting. Some users may need the subnet based on IP address to mount it, hence exposing the IP address of all the mount targets.

Exposing Ids is not required, but I took the reference from aws-rds that we do expose both the identifiers and ip address of all the instances, hence exposing to the user.

Should I remove these for now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably fine, although in practice people are going to want to use the mount targets in the same AZs as their instances (to cut on cross-AZ traffic fees).

Can the construct accomodate that in its current state?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, using the domain name you don't have to: https://docs.aws.amazon.com/efs/latest/ug/mounting-fs-mount-cmd-general.html

Given that I feel the IP addresses are useless without subnet information to identify them, I vote we don't expose any of the mount target information right now and wait for people to come to us with use cases where they need IP addresses. Then they can tell us how they expect to find the IP address corresponding to their AZ.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the mount targets for now.
I can think of a way for exposing the IP address along with the subnet information. Will create another PR for the same.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: a36a011
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify mergify bot dismissed rix0rrr’s stale review March 3, 2020 03:29

Pull request has been modified.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 2caba56
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

rix0rrr
rix0rrr previously requested changes Mar 3, 2020
subnetId
});
this.mountTargets.push(efsMountTarget);
this.mountTargetIdentifiers.push(efsMountTarget.ref);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably fine, although in practice people are going to want to use the mount targets in the same AZs as their instances (to cut on cross-AZ traffic fees).

Can the construct accomodate that in its current state?


fileSystem.connections.allowDefaultPortFrom(inst);

inst.userData.addCommands("yum check-update -y", // Ubuntu: apt-get -y update
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to worry about this at all? I don't see IAM permissions mentioned anywhere in your example:

https://docs.aws.amazon.com/efs/latest/ug/iam-access-control-nfs-efs.html

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default EFS file system policy grants full access to any NFS client that can connect to the file system.

In this example, EFS was not created using any profile permissions, the instance is mounting the file system and hence does require any specific IAM role assigned to it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the IAM feature was recently introduced to EFS. Since I started working on the PR before this feature's launch, I haven't added it here and will add this feature in subsequent PR.

subnetId
});
this.mountTargets.push(efsMountTarget);
this.mountTargetIdentifiers.push(efsMountTarget.ref);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, using the domain name you don't have to: https://docs.aws.amazon.com/efs/latest/ug/mounting-fs-mount-cmd-general.html

Given that I feel the IP addresses are useless without subnet information to identify them, I vote we don't expose any of the mount target information right now and wait for people to come to us with use cases where they need IP addresses. Then they can tell us how they expect to find the IP address corresponding to their AZ.

@mergify mergify bot dismissed rix0rrr’s stale review March 4, 2020 22:58

Pull request has been modified.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: f972d4b
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@rix0rrr rix0rrr changed the title feat(aws-efs): adding construct library for creating EFS feat(efs): create EFS file systems Mar 5, 2020
@mergify
Copy link
Contributor

mergify bot commented Mar 5, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 8cdc403
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify
Copy link
Contributor

mergify bot commented Mar 5, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit a0fb518 into aws:master Mar 5, 2020
eladb pushed a commit that referenced this pull request Mar 9, 2020
* feat(aws-efs): adding construct library for creating EFS

* 100% unit test coverage.
* This was tested by creating an EFS using this construct in a cdk application.
  A instance was also created in this app, which successfully mounted it.

closes #6286

* addressing review comments

* setting correct ipaddress for mount targets

* feat(aws-efs): adding construct library for creating EFS

* 100% unit test coverage.
* This was tested by creating an EFS using this construct in a cdk application.
  A instance was also created in this app, which successfully mounted it.

closes #6286

* addressing review comments

* setting correct ipaddress for mount targets

* address review comments v2

* removing mount targets info

Co-authored-by: Rico Huijbers <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
horsmand pushed a commit to horsmand/aws-cdk that referenced this pull request Mar 9, 2020
* feat(aws-efs): adding construct library for creating EFS

* 100% unit test coverage.
* This was tested by creating an EFS using this construct in a cdk application.
  A instance was also created in this app, which successfully mounted it.

closes aws#6286

* addressing review comments

* setting correct ipaddress for mount targets

* feat(aws-efs): adding construct library for creating EFS

* 100% unit test coverage.
* This was tested by creating an EFS using this construct in a cdk application.
  A instance was also created in this app, which successfully mounted it.

closes aws#6286

* addressing review comments

* setting correct ipaddress for mount targets

* address review comments v2

* removing mount targets info

Co-authored-by: Rico Huijbers <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

AWS EFS service L2 construct
4 participants