Skip to content

Commit 79cb3a5

Browse files
authored
Merge pull request #1233 from otorreno/reduce-efs-calls-reuse-ap
Refactor re-use Access Point
2 parents df6e2ce + 58c8272 commit 79cb3a5

File tree

6 files changed

+355
-274
lines changed

6 files changed

+355
-274
lines changed

pkg/cloud/cloud.go

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ type Efs interface {
9797

9898
type Cloud interface {
9999
GetMetadata() MetadataService
100-
CreateAccessPoint(ctx context.Context, clientToken string, accessPointOpts *AccessPointOptions, reuseAccessPoint bool) (accessPoint *AccessPoint, err error)
100+
CreateAccessPoint(ctx context.Context, clientToken string, accessPointOpts *AccessPointOptions) (accessPoint *AccessPoint, err error)
101101
DeleteAccessPoint(ctx context.Context, accessPointId string) (err error)
102102
DescribeAccessPoint(ctx context.Context, accessPointId string) (accessPoint *AccessPoint, err error)
103+
FindAccessPointByClientToken(ctx context.Context, clientToken, fileSystemId string) (accessPoint *AccessPoint, err error)
103104
ListAccessPoints(ctx context.Context, fileSystemId string) (accessPoints []*AccessPoint, err error)
104105
DescribeFileSystem(ctx context.Context, fileSystemId string) (fs *FileSystem, err error)
105106
DescribeMountTargets(ctx context.Context, fileSystemId, az string) (fs *MountTarget, err error)
@@ -164,26 +165,8 @@ func (c *cloud) GetMetadata() MetadataService {
164165
return c.metadata
165166
}
166167

167-
func (c *cloud) CreateAccessPoint(ctx context.Context, clientToken string, accessPointOpts *AccessPointOptions, reuseAccessPoint bool) (accessPoint *AccessPoint, err error) {
168+
func (c *cloud) CreateAccessPoint(ctx context.Context, clientToken string, accessPointOpts *AccessPointOptions) (accessPoint *AccessPoint, err error) {
168169
efsTags := parseEfsTags(accessPointOpts.Tags)
169-
170-
//if reuseAccessPoint is true, check for AP with same Root Directory exists in efs
171-
// if found reuse that AP
172-
if reuseAccessPoint {
173-
existingAP, err := c.findAccessPointByClientToken(ctx, clientToken, accessPointOpts)
174-
if err != nil {
175-
return nil, fmt.Errorf("failed to find access point: %v", err)
176-
}
177-
if existingAP != nil {
178-
//AP path already exists
179-
klog.V(2).Infof("Existing AccessPoint found : %+v", existingAP)
180-
return &AccessPoint{
181-
AccessPointId: existingAP.AccessPointId,
182-
FileSystemId: existingAP.FileSystemId,
183-
CapacityGiB: accessPointOpts.CapacityGiB,
184-
}, nil
185-
}
186-
}
187170
createAPInput := &efs.CreateAccessPointInput{
188171
ClientToken: &clientToken,
189172
FileSystemId: &accessPointOpts.FileSystemId,
@@ -262,22 +245,22 @@ func (c *cloud) DescribeAccessPoint(ctx context.Context, accessPointId string) (
262245
}, nil
263246
}
264247

265-
func (c *cloud) findAccessPointByClientToken(ctx context.Context, clientToken string, accessPointOpts *AccessPointOptions) (accessPoint *AccessPoint, err error) {
266-
klog.V(5).Infof("AccessPointOptions to find AP : %+v", accessPointOpts)
248+
func (c *cloud) FindAccessPointByClientToken(ctx context.Context, clientToken, fileSystemId string) (accessPoint *AccessPoint, err error) {
249+
klog.V(5).Infof("Filesystem ID to find AP : %+v", fileSystemId)
267250
klog.V(2).Infof("ClientToken to find AP : %s", clientToken)
268251
describeAPInput := &efs.DescribeAccessPointsInput{
269-
FileSystemId: &accessPointOpts.FileSystemId,
252+
FileSystemId: &fileSystemId,
270253
MaxResults: aws.Int64(AccessPointPerFsLimit),
271254
}
272255
res, err := c.efs.DescribeAccessPointsWithContext(ctx, describeAPInput)
273256
if err != nil {
274257
if isAccessDenied(err) {
275-
return
258+
return nil, ErrAccessDenied
276259
}
277260
if isFileSystemNotFound(err) {
278-
return
261+
return nil, ErrNotFound
279262
}
280-
err = fmt.Errorf("failed to list Access Points of efs = %s : %v", accessPointOpts.FileSystemId, err)
263+
err = fmt.Errorf("failed to list Access Points of efs = %s : %v", fileSystemId, err)
281264
return
282265
}
283266
for _, ap := range res.AccessPoints {

pkg/cloud/cloud_test.go

Lines changed: 118 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestCreateAccessPoint(t *testing.T) {
3535
testFunc func(t *testing.T)
3636
}{
3737
{
38-
name: "Success - AP does not exist",
38+
name: "Success",
3939
testFunc: func(t *testing.T) {
4040
mockCtl := gomock.NewController(t)
4141
mockEfs := mocks.NewMockEfs(mockCtl)
@@ -74,63 +74,9 @@ func TestCreateAccessPoint(t *testing.T) {
7474
},
7575
}
7676

77-
describeAPOutput := &efs.DescribeAccessPointsOutput{
78-
AccessPoints: nil,
79-
}
80-
8177
ctx := context.Background()
82-
mockEfs.EXPECT().DescribeAccessPointsWithContext(gomock.Eq(ctx), gomock.Any()).Return(describeAPOutput, nil)
8378
mockEfs.EXPECT().CreateAccessPointWithContext(gomock.Eq(ctx), gomock.Any()).Return(output, nil)
84-
res, err := c.CreateAccessPoint(ctx, clientToken, req, true)
85-
86-
if err != nil {
87-
t.Fatalf("CreateAccessPointFailed is failed: %v", err)
88-
}
89-
90-
if res == nil {
91-
t.Fatal("Result is nil")
92-
}
93-
94-
if accessPointId != res.AccessPointId {
95-
t.Fatalf("AccessPointId mismatched. Expected: %v, Actual: %v", accessPointId, res.AccessPointId)
96-
}
97-
98-
if fsId != res.FileSystemId {
99-
t.Fatalf("FileSystemId mismatched. Expected: %v, Actual: %v", fsId, res.FileSystemId)
100-
}
101-
mockCtl.Finish()
102-
},
103-
},
104-
{
105-
name: "Success - AP already exists",
106-
testFunc: func(t *testing.T) {
107-
mockCtl := gomock.NewController(t)
108-
mockEfs := mocks.NewMockEfs(mockCtl)
109-
c := &cloud{
110-
efs: mockEfs,
111-
}
112-
113-
tags := make(map[string]string)
114-
tags["cluster"] = "efs"
115-
116-
req := &AccessPointOptions{
117-
FileSystemId: fsId,
118-
Uid: uid,
119-
Gid: gid,
120-
DirectoryPerms: directoryPerms,
121-
DirectoryPath: directoryPath,
122-
Tags: tags,
123-
}
124-
125-
describeAPOutput := &efs.DescribeAccessPointsOutput{
126-
AccessPoints: []*efs.AccessPointDescription{
127-
{AccessPointId: aws.String(accessPointId), FileSystemId: aws.String(fsId), ClientToken: aws.String(clientToken), RootDirectory: &efs.RootDirectory{Path: aws.String(directoryPath)}, Tags: []*efs.Tag{{Key: aws.String(PvcNameTagKey), Value: aws.String(volName)}}},
128-
},
129-
}
130-
131-
ctx := context.Background()
132-
mockEfs.EXPECT().DescribeAccessPointsWithContext(gomock.Eq(ctx), gomock.Any()).Return(describeAPOutput, nil)
133-
res, err := c.CreateAccessPoint(ctx, clientToken, req, true)
79+
res, err := c.CreateAccessPoint(ctx, clientToken, req)
13480

13581
if err != nil {
13682
t.Fatalf("CreateAccessPointFailed is failed: %v", err)
@@ -164,14 +110,10 @@ func TestCreateAccessPoint(t *testing.T) {
164110
DirectoryPerms: directoryPerms,
165111
DirectoryPath: directoryPath,
166112
}
167-
describeAPOutput := &efs.DescribeAccessPointsOutput{
168-
AccessPoints: nil,
169-
}
170113

171114
ctx := context.Background()
172-
mockEfs.EXPECT().DescribeAccessPointsWithContext(gomock.Eq(ctx), gomock.Any()).Return(describeAPOutput, nil)
173115
mockEfs.EXPECT().CreateAccessPointWithContext(gomock.Eq(ctx), gomock.Any()).Return(nil, errors.New("CreateAccessPointWithContext failed"))
174-
_, err := c.CreateAccessPoint(ctx, clientToken, req, true)
116+
_, err := c.CreateAccessPoint(ctx, clientToken, req)
175117
if err == nil {
176118
t.Fatalf("CreateAccessPoint did not fail")
177119
}
@@ -195,7 +137,7 @@ func TestCreateAccessPoint(t *testing.T) {
195137

196138
ctx := context.Background()
197139
mockEfs.EXPECT().CreateAccessPointWithContext(gomock.Eq(ctx), gomock.Any()).Return(nil, awserr.New(AccessDeniedException, "Access Denied", errors.New("Access Denied")))
198-
_, err := c.CreateAccessPoint(ctx, clientToken, req, false)
140+
_, err := c.CreateAccessPoint(ctx, clientToken, req)
199141
if err == nil {
200142
t.Fatalf("CreateAccessPoint did not fail")
201143
}
@@ -551,6 +493,119 @@ func TestDescribeAccessPoint(t *testing.T) {
551493
}
552494
}
553495

496+
func TestFindAccessPointByClientToken(t *testing.T) {
497+
var (
498+
fsId = "fs-abcd1234"
499+
accessPointId = "ap-abc123"
500+
clientToken = "token"
501+
path = "/myDir"
502+
Gid int64 = 1000
503+
Uid int64 = 1000
504+
)
505+
testCases := []struct {
506+
name string
507+
testFunc func(t *testing.T)
508+
}{
509+
{
510+
name: "Success - clientToken found",
511+
testFunc: func(t *testing.T) {
512+
mockctl := gomock.NewController(t)
513+
mockEfs := mocks.NewMockEfs(mockctl)
514+
c := &cloud{efs: mockEfs}
515+
516+
output := &efs.DescribeAccessPointsOutput{
517+
AccessPoints: []*efs.AccessPointDescription{
518+
{
519+
AccessPointId: aws.String(accessPointId),
520+
FileSystemId: aws.String(fsId),
521+
ClientToken: aws.String(clientToken),
522+
RootDirectory: &efs.RootDirectory{
523+
Path: aws.String(path),
524+
},
525+
PosixUser: &efs.PosixUser{
526+
Gid: aws.Int64(Gid),
527+
Uid: aws.Int64(Uid),
528+
},
529+
},
530+
},
531+
NextToken: nil,
532+
}
533+
534+
ctx := context.Background()
535+
mockEfs.EXPECT().DescribeAccessPointsWithContext(gomock.Eq(ctx), gomock.Any()).Return(output, nil)
536+
res, err := c.FindAccessPointByClientToken(ctx, clientToken, fsId)
537+
if err != nil {
538+
t.Fatalf("Find Access Point by Client Token failed: %v", err)
539+
}
540+
541+
if res == nil {
542+
t.Fatal("Result is nil")
543+
}
544+
545+
mockctl.Finish()
546+
},
547+
},
548+
{
549+
name: "Success - nil result if clientToken is not found",
550+
testFunc: func(t *testing.T) {
551+
mockctl := gomock.NewController(t)
552+
mockEfs := mocks.NewMockEfs(mockctl)
553+
c := &cloud{efs: mockEfs}
554+
555+
output := &efs.DescribeAccessPointsOutput{
556+
AccessPoints: []*efs.AccessPointDescription{
557+
{
558+
AccessPointId: aws.String(accessPointId),
559+
FileSystemId: aws.String(fsId),
560+
ClientToken: aws.String("differentToken"),
561+
RootDirectory: &efs.RootDirectory{
562+
Path: aws.String(path),
563+
},
564+
PosixUser: &efs.PosixUser{
565+
Gid: aws.Int64(Gid),
566+
Uid: aws.Int64(Uid),
567+
},
568+
},
569+
},
570+
NextToken: nil,
571+
}
572+
573+
ctx := context.Background()
574+
mockEfs.EXPECT().DescribeAccessPointsWithContext(gomock.Eq(ctx), gomock.Any()).Return(output, nil)
575+
res, err := c.FindAccessPointByClientToken(ctx, clientToken, fsId)
576+
if err != nil {
577+
t.Fatalf("Find Access Point by Client Token failed: %v", err)
578+
}
579+
580+
if res != nil {
581+
t.Fatal("Result should be nil. No access point with the specified token")
582+
}
583+
584+
mockctl.Finish()
585+
},
586+
},
587+
{
588+
name: "Fail - Access Denied",
589+
testFunc: func(t *testing.T) {
590+
mockctl := gomock.NewController(t)
591+
mockEfs := mocks.NewMockEfs(mockctl)
592+
c := &cloud{efs: mockEfs}
593+
ctx := context.Background()
594+
mockEfs.EXPECT().DescribeAccessPointsWithContext(gomock.Eq(ctx), gomock.Any()).Return(nil, awserr.New(AccessDeniedException, "Access Denied", errors.New("Access Denied")))
595+
_, err := c.FindAccessPointByClientToken(ctx, clientToken, fsId)
596+
if err == nil {
597+
t.Fatalf("Find Access Point by Client Token should have failed: %v", err)
598+
}
599+
600+
mockctl.Finish()
601+
},
602+
},
603+
}
604+
for _, tc := range testCases {
605+
t.Run(tc.name, tc.testFunc)
606+
}
607+
}
608+
554609
func TestListAccessPoints(t *testing.T) {
555610
var (
556611
fsId = "fs-abcd1234"
@@ -1024,7 +1079,7 @@ func Test_findAccessPointByPath(t *testing.T) {
10241079
tt.prepare(mockEfs)
10251080
}
10261081

1027-
gotAccessPoint, err := c.findAccessPointByClientToken(ctx, tt.args.clientToken, tt.args.accessPointOpts)
1082+
gotAccessPoint, err := c.FindAccessPointByClientToken(ctx, tt.args.clientToken, tt.args.accessPointOpts.FileSystemId)
10281083
if (err != nil) != tt.wantErr {
10291084
t.Errorf("findAccessPointByClientToken() error = %v, wantErr %v", err, tt.wantErr)
10301085
return

pkg/cloud/fakes.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (c *FakeCloudProvider) GetMetadata() MetadataService {
2727
return c.m
2828
}
2929

30-
func (c *FakeCloudProvider) CreateAccessPoint(ctx context.Context, clientToken string, accessPointOpts *AccessPointOptions, usePvcName bool) (accessPoint *AccessPoint, err error) {
30+
func (c *FakeCloudProvider) CreateAccessPoint(ctx context.Context, clientToken string, accessPointOpts *AccessPointOptions) (accessPoint *AccessPoint, err error) {
3131
ap, exists := c.accessPoints[clientToken]
3232
if exists {
3333
if accessPointOpts.CapacityGiB == ap.CapacityGiB {
@@ -98,6 +98,14 @@ func (c *FakeCloudProvider) DescribeMountTargets(ctx context.Context, fileSystem
9898
return nil, ErrNotFound
9999
}
100100

101+
func (c *FakeCloudProvider) FindAccessPointByClientToken(ctx context.Context, clientToken, fileSystemId string) (accessPoint *AccessPoint, err error) {
102+
if ap, exists := c.accessPoints[clientToken]; exists {
103+
return ap, nil
104+
} else {
105+
return nil, nil
106+
}
107+
}
108+
101109
func (c *FakeCloudProvider) ListAccessPoints(ctx context.Context, fileSystemId string) ([]*AccessPoint, error) {
102110
accessPoints := []*AccessPoint{
103111
c.accessPoints[fileSystemId],

0 commit comments

Comments
 (0)