diff --git a/sdk/storage/azdatalake/assets.json b/sdk/storage/azdatalake/assets.json index 0f87599cacfb..67a2df2961e2 100644 --- a/sdk/storage/azdatalake/assets.json +++ b/sdk/storage/azdatalake/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/storage/azdatalake", - "Tag": "go/storage/azdatalake_db1de4a48b" + "Tag": "go/storage/azdatalake_9dd1cc3e0e" } \ No newline at end of file diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index b1e0fc9dec56..8c998a0f812b 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -12,10 +12,17 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/base" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "net/http" + "net/url" + "strings" + "time" ) // ClientOptions contains the optional parameters when creating a Client. @@ -38,7 +45,7 @@ func NewClient(directoryURL string, cred azcore.TokenCredential, options *Client } base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) - azClient, err := azcore.NewClient(shared.FileClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + azClient, err := azcore.NewClient(shared.DirectoryClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) if err != nil { return nil, err } @@ -154,6 +161,10 @@ func (d *Client) blobClient() *blockblob.Client { return blobClient } +func (d *Client) getClientOptions() *base.ClientOptions { + return base.GetCompositeClientOptions((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) +} + func (d *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) } @@ -176,63 +187,187 @@ func (d *Client) BlobURL() string { // Create creates a new directory (dfs1). func (d *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { - return CreateResponse{}, nil + lac, mac, httpHeaders, createOpts, cpkOpts := options.format() + resp, err := d.generatedDirClientWithDFS().Create(ctx, createOpts, httpHeaders, lac, mac, nil, cpkOpts) + err = exported.ConvertToDFSError(err) + return resp, err } -// Delete removes the directory (dfs1). +// Delete deletes directory and any path under it (dfs1). func (d *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { - //TODO: pass recursive = true - return DeleteResponse{}, nil + lac, mac, deleteOpts := path.FormatDeleteOptions(options, true) + resp, err := d.generatedDirClientWithDFS().Delete(ctx, deleteOpts, lac, mac) + err = exported.ConvertToDFSError(err) + return resp, err } -// GetProperties returns the properties of the directory (blob3). #TODO: we may just move this method to path client +// GetProperties gets the properties of a directory (blob3) func (d *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { - // TODO: format blob response to path response - return GetPropertiesResponse{}, nil + opts := path.FormatGetPropertiesOptions(options) + var respFromCtx *http.Response + ctxWithResp := runtime.WithCaptureResponse(ctx, &respFromCtx) + resp, err := d.blobClient().GetProperties(ctxWithResp, opts) + newResp := path.FormatGetPropertiesResponse(&resp, respFromCtx) + err = exported.ConvertToDFSError(err) + return newResp, err } -// Rename renames the directory (dfs1). +func (d *Client) renamePathInURL(newName string) (string, string, string) { + endpoint := d.DFSURL() + separator := "/" + // Find the index of the last occurrence of the separator + lastIndex := strings.LastIndex(endpoint, separator) + // Split the string based on the last occurrence of the separator + firstPart := endpoint[:lastIndex] // From the beginning of the string to the last occurrence of the separator + newPathURL, newBlobURL := shared.GetURLs(runtime.JoinPaths(firstPart, newName)) + parsedNewURL, _ := url.Parse(d.DFSURL()) + return parsedNewURL.Path, newPathURL, newBlobURL +} + +// Rename renames a directory (dfs1) func (d *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { - return RenameResponse{}, nil + newPathWithoutURL, newBlobURL, newPathURL := d.renamePathInURL(newName) + lac, mac, smac, createOpts := path.FormatRenameOptions(options, newPathWithoutURL) + var newBlobClient *blockblob.Client + var err error + if d.identityCredential() != nil { + newBlobClient, err = blockblob.NewClient(newBlobURL, *d.identityCredential(), nil) + } else if d.sharedKey() != nil { + blobSharedKey, _ := d.sharedKey().ConvertToBlobSharedKey() + newBlobClient, err = blockblob.NewClientWithSharedKeyCredential(newBlobURL, blobSharedKey, nil) + } else { + newBlobClient, err = blockblob.NewClientWithNoCredential(newBlobURL, nil) + } + if err != nil { + return RenameResponse{}, err + } + newDirClient := (*Client)(base.NewPathClient(newPathURL, newBlobURL, newBlobClient, d.generatedDirClientWithDFS().InternalClient().WithClientName(shared.DirectoryClient), d.sharedKey(), d.identityCredential(), d.getClientOptions())) + resp, err := newDirClient.generatedDirClientWithDFS().Create(ctx, createOpts, nil, lac, mac, smac, nil) + return RenameResponse{ + Response: resp, + NewDirectoryClient: newDirClient, + }, exported.ConvertToDFSError(err) } -// SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). +// SetAccessControl sets the owner, owning group, and permissions for a directory (dfs1). func (d *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { - return SetAccessControlResponse{}, nil + opts, lac, mac, err := path.FormatSetAccessControlOptions(options) + if err != nil { + return SetAccessControlResponse{}, err + } + resp, err := d.generatedDirClientWithDFS().SetAccessControl(ctx, opts, lac, mac) + err = exported.ConvertToDFSError(err) + return resp, err } -// SetAccessControlRecursive sets the owner, owning group, and permissions for a file or directory (dfs1). -func (d *Client) SetAccessControlRecursive(ctx context.Context, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil +func (d *Client) setAccessControlHelper(mode generated.PathSetAccessControlRecursiveMode, listOptions *generated.PathClientSetAccessControlRecursiveOptions) *runtime.Pager[SetAccessControlRecursiveResponse] { + return runtime.NewPager(runtime.PagingHandler[SetAccessControlRecursiveResponse]{ + More: func(page SetAccessControlRecursiveResponse) bool { + return page.Continuation != nil && len(*page.Continuation) > 0 + }, + Fetcher: func(ctx context.Context, page *SetAccessControlRecursiveResponse) (SetAccessControlRecursiveResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = d.generatedDirClientWithDFS().SetAccessControlRecursiveCreateRequest(ctx, mode, listOptions) + err = exported.ConvertToDFSError(err) + } else { + listOptions.Continuation = page.Continuation + req, err = d.generatedDirClientWithDFS().SetAccessControlRecursiveCreateRequest(ctx, mode, listOptions) + err = exported.ConvertToDFSError(err) + } + if err != nil { + return SetAccessControlRecursiveResponse{}, err + } + resp, err := d.generatedDirClientWithDFS().InternalClient().Pipeline().Do(req) + err = exported.ConvertToDFSError(err) + if err != nil { + return SetAccessControlRecursiveResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return SetAccessControlRecursiveResponse{}, runtime.NewResponseError(resp) + } + newResp, err := d.generatedDirClientWithDFS().SetAccessControlRecursiveHandleResponse(resp) + return newResp, exported.ConvertToDFSError(err) + }, + }) + } -// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a file or directory (dfs1). -func (d *Client) UpdateAccessControlRecursive(ctx context.Context, options *UpdateAccessControlRecursiveOptions) (UpdateAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil +// NewSetAccessControlRecursivePager sets the owner, owning group, and permissions for a directory (dfs1). +func (d *Client) NewSetAccessControlRecursivePager(ACL string, options *SetAccessControlRecursiveOptions) *runtime.Pager[SetAccessControlRecursiveResponse] { + mode, listOptions := options.format(ACL, "set") + return d.setAccessControlHelper(mode, listOptions) } -// GetAccessControl gets the owner, owning group, and permissions for a file or directory (dfs1). -func (d *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { - return GetAccessControlResponse{}, nil +// NewUpdateAccessControlRecursivePager updates the owner, owning group, and permissions for a directory (dfs1). +func (d *Client) NewUpdateAccessControlRecursivePager(ACL string, options *UpdateAccessControlRecursiveOptions) *runtime.Pager[UpdateAccessControlRecursiveResponse] { + mode, listOptions := options.format(ACL, "modify") + return d.setAccessControlHelper(mode, listOptions) +} + +// NewRemoveAccessControlRecursivePager removes the owner, owning group, and permissions for a directory (dfs1). +func (d *Client) NewRemoveAccessControlRecursivePager(ACL string, options *RemoveAccessControlRecursiveOptions) *runtime.Pager[RemoveAccessControlRecursiveResponse] { + mode, listOptions := options.format(ACL, "remove") + return d.setAccessControlHelper(mode, listOptions) } -// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a file or directory (dfs1). -func (d *Client) RemoveAccessControlRecursive(ctx context.Context, options *RemoveAccessControlRecursiveOptions) (RemoveAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil +// GetAccessControl gets the owner, owning group, and permissions for a directory (dfs1). +func (d *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { + opts, lac, mac := path.FormatGetAccessControlOptions(options) + resp, err := d.generatedDirClientWithDFS().GetProperties(ctx, opts, lac, mac) + err = exported.ConvertToDFSError(err) + return resp, err } -// SetMetadata sets the metadata for a file or directory (blob3). +// SetMetadata sets the metadata for a directory (blob3). func (d *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { - // TODO: call directly into blob - return SetMetadataResponse{}, nil + opts, metadata := path.FormatSetMetadataOptions(options) + resp, err := d.blobClient().SetMetadata(ctx, metadata, opts) + err = exported.ConvertToDFSError(err) + return resp, err } -// SetHTTPHeaders sets the HTTP headers for a file or directory (blob3). +// SetHTTPHeaders sets the HTTP headers for a directory (blob3). func (d *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, options *SetHTTPHeadersOptions) (SetHTTPHeadersResponse, error) { - // TODO: call formatBlobHTTPHeaders() since we want to add the blob prefix to our options before calling into blob - // TODO: call into blob - return SetHTTPHeadersResponse{}, nil + opts, blobHTTPHeaders := path.FormatSetHTTPHeadersOptions(options, httpHeaders) + resp, err := d.blobClient().SetHTTPHeaders(ctx, blobHTTPHeaders, opts) + newResp := SetHTTPHeadersResponse{} + path.FormatSetHTTPHeadersResponse(&newResp, &resp) + err = exported.ConvertToDFSError(err) + return newResp, err +} + +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at blob. +// It can only be used if the credential supplied during creation was a SharedKeyCredential. +func (f *Client) GetSASURL(permissions sas.DirectoryPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + if f.sharedKey() == nil { + return "", datalakeerror.MissingSharedKeyCredential + } + + urlParts, err := sas.ParseURL(f.BlobURL()) + err = exported.ConvertToDFSError(err) + if err != nil { + return "", err + } + + st := path.FormatGetSASURLOptions(o) + + qps, err := sas.DatalakeSignatureValues{ + DirectoryPath: urlParts.PathName, + FilesystemName: urlParts.FilesystemName, + Version: sas.Version, + Permissions: permissions.String(), + StartTime: st, + ExpiryTime: expiry.UTC(), + }.SignWithSharedKey(f.sharedKey()) + + err = exported.ConvertToDFSError(err) + if err != nil { + return "", err + } + + endpoint := f.BlobURL() + "?" + qps.Encode() + + return endpoint, nil } diff --git a/sdk/storage/azdatalake/directory/client_test.go b/sdk/storage/azdatalake/directory/client_test.go new file mode 100644 index 000000000000..2a11a11d0751 --- /dev/null +++ b/sdk/storage/azdatalake/directory/client_test.go @@ -0,0 +1,2215 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package directory_test + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/directory" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "testing" + "time" +) + +var proposedLeaseIDs = []*string{to.Ptr("c820a799-76d7-4ee2-6e15-546f19325c2c"), to.Ptr("326cc5e1-746e-4af8-4811-a50e6629a8ca")} + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running datalake Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &RecordedTestSuite{}) + suite.Run(t, &UnrecordedTestSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &RecordedTestSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &RecordedTestSuite{}) + } +} + +func (s *RecordedTestSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(s.T(), suite, test) +} + +func (s *RecordedTestSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(s.T(), suite, test) +} + +func (s *UnrecordedTestSuite) BeforeTest(suite string, test string) { + +} + +func (s *UnrecordedTestSuite) AfterTest(suite string, test string) { + +} + +type RecordedTestSuite struct { + suite.Suite +} + +type UnrecordedTestSuite struct { + suite.Suite +} + +func (s *RecordedTestSuite) TestCreateDirAndDelete() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateDirWithNilAccessConditions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + createDirOpts := &directory.CreateOptions{ + AccessConditions: nil, + } + + resp, err = dirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateDirIfModifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + DirName := testcommon.GenerateDirName(testName) + DirClient, err := testcommon.GetDirClient(filesystemName, DirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, DirClient) + + resp, err := DirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + createDirOpts := &directory.CreateOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + resp, err = DirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateDirIfModifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + DirName := testcommon.GenerateDirName(testName) + DirClient, err := testcommon.GetDirClient(filesystemName, DirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, DirClient) + + resp, err := DirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + createDirOpts := &directory.CreateOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + resp, err = DirClient.Create(context.Background(), createDirOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestCreateDirIfUnmodifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + createDirOpts := &directory.CreateOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + resp, err = dirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileIfUnmodifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + createDirOpts := &directory.CreateOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + resp, err = dirClient.Create(context.Background(), createDirOpts) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestCreateFileIfETagMatch() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + createDirOpts := &directory.CreateOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + resp, err = dirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileIfETagMatchFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + createDirOpts := &directory.CreateOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }, + } + + resp, err = dirClient.Create(context.Background(), createDirOpts) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestCreateFileWithMetadataNotNil() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createDirOpts := &directory.CreateOptions{ + Metadata: testcommon.BasicMetadata, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileWithEmptyMetadata() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createDirOpts := &directory.CreateOptions{ + Metadata: nil, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileWithNilHTTPHeaders() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createDirOpts := &directory.CreateOptions{ + HTTPHeaders: nil, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileWithHTTPHeaders() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createDirOpts := &directory.CreateOptions{ + HTTPHeaders: &testcommon.BasicHeaders, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), createDirOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateDirWithLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createFileOpts := &directory.CreateOptions{ + ProposedLeaseID: proposedLeaseIDs[0], + LeaseDuration: to.Ptr(int64(15)), + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + // should fail since leased + _, err = dirClient.Create(context.Background(), createFileOpts) + _require.NotNil(err) + + time.Sleep(time.Second * 15) + resp, err = dirClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateDirWithPermissions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + perms := "0777" + umask := "0000" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createFileOpts := &directory.CreateOptions{ + Permissions: &perms, + Umask: &umask, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + resp2, err := dirClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp2) + _require.Equal("rwxrwxrwx", *resp2.Permissions) +} + +func (s *RecordedTestSuite) TestCreateDirWithOwnerGroupACLUmask() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + umask := "0000" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createFileOpts := &directory.CreateOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + Umask: &umask, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + +} + +func (s *RecordedTestSuite) TestDeleteDirWithNilAccessConditions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + + deleteOpts := &directory.DeleteOptions{ + AccessConditions: nil, + } + + resp, err := dirClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestDeleteDirIfModifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + deleteOpts := &directory.DeleteOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + resp1, err := dirClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp1) +} + +func (s *RecordedTestSuite) TestDeleteDirIfModifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + deleteOpts := &directory.DeleteOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.Delete(context.Background(), deleteOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestDeleteDirIfUnmodifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + deleteOpts := &directory.DeleteOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestDeleteDirIfUnmodifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + deleteOpts := &directory.DeleteOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.Delete(context.Background(), deleteOpts) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestDeleteDirIfETagMatch() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + deleteOpts := &directory.DeleteOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + _, err = dirClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestDeleteDirIfETagMatchFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + deleteOpts := &directory.DeleteOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }, + } + + _, err = dirClient.Delete(context.Background(), deleteOpts) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestSetAccessControlNil() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = dirClient.SetAccessControl(context.Background(), nil) + _require.NotNil(err) + + _require.Equal(err, datalakeerror.MissingParameters) +} + +// TODO: write test that fails if you provide permissions and acls +func (s *RecordedTestSuite) TestSetAccessControl() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetAccessControlWithNilAccessConditions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: nil, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }} + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestSetAccessControlIfETagMatch() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + etag := resp.ETag + + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetAccessControlIfETagMatchFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }} + + _, err = dirClient.SetAccessControl(context.Background(), opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestGetAccessControl() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + getACLResp, err := dirClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestGetAccessControlWithSAS() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + // Adding SAS and options + permissions := sas.DirectoryPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Delete: true, + } + expiry := time.Now().Add(time.Hour) + + sasURL, err := dirClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + dirClient2, _ := directory.NewClientWithNoCredential(sasURL, nil) + + getACLResp, err := dirClient2.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestDeleteWithSAS() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // Adding SAS and options + permissions := sas.DirectoryPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Delete: true, + } + expiry := time.Now().Add(time.Hour) + + sasURL, err := dirClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + dirClient2, _ := directory.NewClientWithNoCredential(sasURL, nil) + + _, err = dirClient2.Delete(context.Background(), nil) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestGetAccessControlWithNilAccessConditions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + opts := &directory.GetAccessControlOptions{ + AccessConditions: nil, + } + + getACLResp, err := dirClient.GetAccessControl(context.Background(), opts) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + opts := &directory.GetAccessControlOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + getACLResp, err := dirClient.GetAccessControl(context.Background(), opts) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &directory.GetAccessControlOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.GetAccessControl(context.Background(), opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + opts := &directory.GetAccessControlOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }} + + getACLResp, err := dirClient.GetAccessControl(context.Background(), opts) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &directory.GetAccessControlOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.GetAccessControl(context.Background(), opts) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestGetAccessControlIfETagMatch() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + etag := resp.ETag + + opts := &directory.GetAccessControlOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + getACLResp, err := dirClient.GetAccessControl(context.Background(), opts) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestGetAccessControlIfETagMatchFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + opts := &directory.GetAccessControlOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }} + + _, err = dirClient.GetAccessControl(context.Background(), opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +///===================================================================== + +func (s *RecordedTestSuite) TestUpdateAccessControlRecursive() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "user::rwx,group::r-x,other::rwx" + acl1 := "user::rwx,group::r--,other::r--" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createOpts := &directory.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + pager := dirClient.NewUpdateAccessControlRecursivePager(acl1, nil) + + for pager.More() { + resp1, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(*resp1.SetAccessControlRecursiveResponse.DirectoriesSuccessful, int32(1)) + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestRemoveAccessControlRecursive() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + acl := "mask," + "default:user,default:group," + + "user:ec3595d6-2c17-4696-8caa-7e139758d24a,group:ec3595d6-2c17-4696-8caa-7e139758d24a," + + "default:user:ec3595d6-2c17-4696-8caa-7e139758d24a,default:group:ec3595d6-2c17-4696-8caa-7e139758d24a" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + pager := dirClient.NewRemoveAccessControlRecursivePager(acl, nil) + + for pager.More() { + resp1, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(*resp1.SetAccessControlRecursiveResponse.DirectoriesSuccessful, int32(1)) + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestSetMetadataNil() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = dirClient.SetMetadata(context.Background(), nil) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetMetadataWithEmptyOpts() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + opts := &directory.SetMetadataOptions{ + Metadata: nil, + } + _, err = dirClient.SetMetadata(context.Background(), opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetMetadataWithBasicMetadata() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + opts := &directory.SetMetadataOptions{ + Metadata: testcommon.BasicMetadata, + } + _, err = dirClient.SetMetadata(context.Background(), opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetMetadataWithAccessConditions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteDir(context.Background(), _require, dirClient) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &directory.SetMetadataOptions{ + Metadata: testcommon.BasicMetadata, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = dirClient.SetMetadata(context.Background(), opts) + _require.Nil(err) +} + +func validatePropertiesSet(_require *require.Assertions, dirClient *directory.Client, disposition string) { + resp, err := dirClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.Equal(*resp.ContentDisposition, disposition) +} + +func (s *RecordedTestSuite) TestSetHTTPHeaders() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, nil) + _require.Nil(err) + validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) +} + +func (s *RecordedTestSuite) TestSetHTTPHeadersWithNilAccessConditions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + opts := &directory.SetHTTPHeadersOptions{ + AccessConditions: nil, + } + + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) +} + +func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &directory.SetHTTPHeadersOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) +} + +func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &directory.SetHTTPHeadersOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &directory.SetHTTPHeadersOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) +} + +func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &directory.SetHTTPHeadersOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatch() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + opts := &directory.SetHTTPHeadersOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfMatch: etag, + }, + }} + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) +} + +func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatchFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + opts := &directory.SetHTTPHeadersOptions{ + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }, + } + _, err = dirClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestRenameNoOptions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + resp1, err := dirClient.Rename(context.Background(), "newName", nil) + _require.Nil(err) + _require.NotNil(resp1) + _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") +} + +func (s *RecordedTestSuite) TestRenameFileWithNilAccessConditions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + renameFileOpts := &directory.RenameOptions{ + AccessConditions: nil, + } + + resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) + _require.NotNil(resp1) + _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") +} + +func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + renameFileOpts := &directory.RenameOptions{ + SourceAccessConditions: &directory.SourceAccessConditions{ + SourceModifiedAccessConditions: &directory.SourceModifiedAccessConditions{ + SourceIfModifiedSince: ¤tTime, + }, + }, + } + resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) + _require.NotNil(resp1) + _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") +} + +func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + renameFileOpts := &directory.RenameOptions{ + SourceAccessConditions: &directory.SourceAccessConditions{ + SourceModifiedAccessConditions: &directory.SourceModifiedAccessConditions{ + SourceIfModifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) +} + +func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceTrue() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + renameFileOpts := &directory.RenameOptions{ + SourceAccessConditions: &directory.SourceAccessConditions{ + SourceModifiedAccessConditions: &directory.SourceModifiedAccessConditions{ + SourceIfUnmodifiedSince: ¤tTime, + }, + }, + } + + resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(resp1) + _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") +} + +func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + renameFileOpts := &directory.RenameOptions{ + SourceAccessConditions: &directory.SourceAccessConditions{ + SourceModifiedAccessConditions: &directory.SourceModifiedAccessConditions{ + SourceIfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) +} + +func (s *RecordedTestSuite) TestRenameFileIfETagMatch() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + renameFileOpts := &directory.RenameOptions{ + SourceAccessConditions: &directory.SourceAccessConditions{ + SourceModifiedAccessConditions: &directory.SourceModifiedAccessConditions{ + SourceIfMatch: etag, + }, + }, + } + + resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(resp1) + _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") +} + +func (s *RecordedTestSuite) TestRenameFileIfETagMatchFalse() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + dirName := testcommon.GenerateDirName(testName) + dirClient, err := testcommon.GetDirClient(filesystemName, dirName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + renameFileOpts := &directory.RenameOptions{ + SourceAccessConditions: &directory.SourceAccessConditions{ + SourceModifiedAccessConditions: &directory.SourceModifiedAccessConditions{ + SourceIfNoneMatch: etag, + }, + }, + } + + _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) +} + +// TODO: more tests for acls diff --git a/sdk/storage/azdatalake/directory/models.go b/sdk/storage/azdatalake/directory/models.go index ff71be61b95d..517fdf0cda44 100644 --- a/sdk/storage/azdatalake/directory/models.go +++ b/sdk/storage/azdatalake/directory/models.go @@ -10,10 +10,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" - "time" ) -// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint +// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. type CreateOptions struct { // AccessConditions contains parameters for accessing the file. AccessConditions *AccessConditions @@ -23,9 +22,10 @@ type CreateOptions struct { CPKInfo *CPKInfo // HTTPHeaders contains the HTTP headers for path operations. HTTPHeaders *HTTPHeaders - //PathExpiryOptions *ExpiryOptions - // LeaseDuration specifies the duration of the lease. - LeaseDuration *time.Duration + // LeaseDuration specifies the duration of the lease, in seconds, or negative one + // (-1) for a lease that never expires. A non-infinite lease can be + // between 15 and 60 seconds. + LeaseDuration *int64 // ProposedLeaseID specifies the proposed lease ID for the file. ProposedLeaseID *string // Permissions is the octal representation of the permissions for user, group and mask. @@ -40,97 +40,78 @@ type CreateOptions struct { ACL *string } -func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, *generated.PathHTTPHeaders, error) { - // TODO: add all other required options for the create operation, we don't need sourceModAccCond since this is not rename +func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, *generated.PathHTTPHeaders, *generated.PathClientCreateOptions, *generated.CPKInfo) { + resource := generated.PathResourceTypeDirectory + createOpts := &generated.PathClientCreateOptions{ + Resource: &resource, + } + if o == nil { + return nil, nil, nil, createOpts, nil + } leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - httpHeaders := &generated.PathHTTPHeaders{ - CacheControl: o.HTTPHeaders.CacheControl, - ContentDisposition: o.HTTPHeaders.ContentDisposition, - ContentEncoding: o.HTTPHeaders.ContentEncoding, - ContentLanguage: o.HTTPHeaders.ContentLanguage, - ContentMD5: o.HTTPHeaders.ContentMD5, - ContentType: o.HTTPHeaders.ContentType, - TransactionalContentHash: o.HTTPHeaders.ContentMD5, + createOpts.ACL = o.ACL + createOpts.Group = o.Group + createOpts.Owner = o.Owner + createOpts.Umask = o.Umask + createOpts.Permissions = o.Permissions + createOpts.ProposedLeaseID = o.ProposedLeaseID + createOpts.LeaseDuration = o.LeaseDuration + + var httpHeaders *generated.PathHTTPHeaders + var cpkOpts *generated.CPKInfo + + if o.HTTPHeaders != nil { + httpHeaders = path.FormatPathHTTPHeaders(o.HTTPHeaders) } - return leaseAccessConditions, modifiedAccessConditions, httpHeaders, nil + if o.CPKInfo != nil { + cpkOpts = &generated.CPKInfo{ + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + } + } + return leaseAccessConditions, modifiedAccessConditions, httpHeaders, createOpts, cpkOpts } // DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint -type DeleteOptions struct { - // AccessConditions specifies parameters for accessing the directory - AccessConditions *AccessConditions -} +type DeleteOptions = path.DeleteOptions -func (o *DeleteOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - return leaseAccessConditions, modifiedAccessConditions, nil -} - -type RenameOptions struct { - // SourceModifiedAccessConditions specifies parameters for accessing the source directory - SourceModifiedAccessConditions *SourceModifiedAccessConditions - // AccessConditions specifies parameters for accessing the destination directory - AccessConditions *AccessConditions -} +// RenameOptions contains the optional parameters when calling the Rename operation. +type RenameOptions = path.RenameOptions // ===================================== PATH IMPORTS =========================================== // SetAccessControlRecursiveOptions contains the optional parameters when calling the SetAccessControlRecursive operation. TODO: Design formatter -type SetAccessControlRecursiveOptions struct { - // ACL is the access control list for the path. - ACL *string - // BatchSize is the number of paths to set access control recursively in a single call. - BatchSize *int32 - // MaxBatches is the maximum number of batches to perform the operation on. - MaxBatches *int32 +type accessControlRecursiveOptions struct { + MaxResults *int32 // ContinueOnFailure indicates whether to continue on failure when the operation encounters an error. ContinueOnFailure *bool // Marker is the continuation token to use when continuing the operation. Marker *string } -func (o *SetAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { - // TODO: design formatter - return nil, nil +func (o *accessControlRecursiveOptions) format(ACL, mode string) (generated.PathSetAccessControlRecursiveMode, *generated.PathClientSetAccessControlRecursiveOptions) { + opts := &generated.PathClientSetAccessControlRecursiveOptions{ + ACL: &ACL, + } + newMode := generated.PathSetAccessControlRecursiveMode(mode) + if o == nil { + return newMode, opts + } + opts.ForceFlag = o.ContinueOnFailure + opts.Continuation = o.Marker + opts.MaxRecords = o.MaxResults + return newMode, opts } -// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. TODO: Design formatter -type UpdateAccessControlRecursiveOptions struct { - // ACL is the access control list for the path. - ACL *string - // BatchSize is the number of paths to set access control recursively in a single call. - BatchSize *int32 - // MaxBatches is the maximum number of batches to perform the operation on. - MaxBatches *int32 - // ContinueOnFailure indicates whether to continue on failure when the operation encounters an error. - ContinueOnFailure *bool - // Marker is the continuation token to use when continuing the operation. - Marker *string -} +// SetAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. TODO: Design formatter +type SetAccessControlRecursiveOptions = accessControlRecursiveOptions -func (o *UpdateAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { - // TODO: design formatter - similar to SetAccessControlRecursiveOptions - return nil, nil -} +// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. TODO: Design formatter +type UpdateAccessControlRecursiveOptions = accessControlRecursiveOptions // RemoveAccessControlRecursiveOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. TODO: Design formatter -type RemoveAccessControlRecursiveOptions struct { - // ACL is the access control list for the path. - ACL *string - // BatchSize is the number of paths to set access control recursively in a single call. - BatchSize *int32 - // MaxBatches is the maximum number of batches to perform the operation on. - MaxBatches *int32 - // ContinueOnFailure indicates whether to continue on failure when the operation encounters an error. - ContinueOnFailure *bool - // Marker is the continuation token to use when continuing the operation. - Marker *string -} - -func (o *RemoveAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { - // TODO: design formatter - similar to SetAccessControlRecursiveOptions - return nil, nil -} +type RemoveAccessControlRecursiveOptions = accessControlRecursiveOptions // ================================= path imports ================================== diff --git a/sdk/storage/azdatalake/directory/responses.go b/sdk/storage/azdatalake/directory/responses.go index e87136e9b0a6..dc2ad337ddb9 100644 --- a/sdk/storage/azdatalake/directory/responses.go +++ b/sdk/storage/azdatalake/directory/responses.go @@ -18,7 +18,10 @@ type CreateResponse = generated.PathClientCreateResponse type DeleteResponse = generated.PathClientDeleteResponse // RenameResponse contains the response fields for the Create operation. -type RenameResponse = generated.PathClientCreateResponse +type RenameResponse struct { + Response generated.PathClientCreateResponse + NewDirectoryClient *Client +} // SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index 0fae799fb965..7400838cf7fb 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -200,7 +200,7 @@ func (f *Client) Create(ctx context.Context, options *CreateOptions) (CreateResp // Delete deletes a file (dfs1). func (f *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { - lac, mac, deleteOpts := options.format() + lac, mac, deleteOpts := path.FormatDeleteOptions(options, false) resp, err := f.generatedFileClientWithDFS().Delete(ctx, deleteOpts, lac, mac) err = exported.ConvertToDFSError(err) return resp, err @@ -232,7 +232,7 @@ func (f *Client) renamePathInURL(newName string) (string, string, string) { // Rename renames a file (dfs1) func (f *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { newPathWithoutURL, newBlobURL, newPathURL := f.renamePathInURL(newName) - lac, mac, smac, createOpts := options.format(newPathWithoutURL) + lac, mac, smac, createOpts := path.FormatRenameOptions(options, newPathWithoutURL) var newBlobClient *blockblob.Client var err error if f.identityCredential() != nil { @@ -377,7 +377,7 @@ func (f *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actua return errors.New("buffer is too large to upload to a file") } if o.ChunkSize == 0 { - o.ChunkSize = MaxUpdateRangeBytes + o.ChunkSize = MaxAppendBytes } if log.Should(exported.EventUpload) { diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index 1f628860bded..55c2a781be83 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -24,14 +24,11 @@ const ( _1MiB = 1024 * 1024 CountToEnd = 0 - // MaxUpdateRangeBytes indicates the maximum number of bytes that can be updated in a call to Client.UploadRange. - MaxUpdateRangeBytes = 4 * 1024 * 1024 // 4MiB + // MaxAppendBytes indicates the maximum number of bytes that can be updated in a call to Client.UploadRange. + MaxAppendBytes = 100 * 1024 * 1024 // 100iB // MaxFileSize indicates the maximum size of the file allowed. MaxFileSize = 4 * 1024 * 1024 * 1024 * 1024 // 4 TiB - - // DefaultDownloadChunkSize is default chunk size - DefaultDownloadChunkSize = int64(4 * 1024 * 1024) // 4MiB ) // CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. @@ -97,7 +94,7 @@ func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.M } if o.CPKInfo != nil { cpkOpts = &generated.CPKInfo{ - EncryptionAlgorithm: (*generated.EncryptionAlgorithmType)(o.CPKInfo.EncryptionAlgorithm), + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, EncryptionKey: o.CPKInfo.EncryptionKey, EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, } @@ -105,62 +102,6 @@ func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.M return leaseAccessConditions, modifiedAccessConditions, httpHeaders, createOpts, cpkOpts } -// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint -type DeleteOptions struct { - // AccessConditions contains parameters for accessing the file. - AccessConditions *AccessConditions -} - -func (o *DeleteOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, *generated.PathClientDeleteOptions) { - recursive := false - deleteOpts := &generated.PathClientDeleteOptions{ - Recursive: &recursive, - } - if o == nil { - return nil, nil, deleteOpts - } - leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - return leaseAccessConditions, modifiedAccessConditions, deleteOpts -} - -// RenameOptions contains the optional parameters when calling the Rename operation. -type RenameOptions struct { - // SourceAccessConditions identifies the source path access conditions. - SourceAccessConditions *SourceAccessConditions - // AccessConditions contains parameters for accessing the file. - AccessConditions *AccessConditions -} - -func (o *RenameOptions) format(path string) (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, *generated.SourceModifiedAccessConditions, *generated.PathClientCreateOptions) { - // we don't need sourceModAccCond since this is not rename - mode := generated.PathRenameModeLegacy - createOpts := &generated.PathClientCreateOptions{ - Mode: &mode, - RenameSource: &path, - } - if o == nil { - return nil, nil, nil, createOpts - } - leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - if o.SourceAccessConditions != nil { - if o.SourceAccessConditions.SourceLeaseAccessConditions != nil { - createOpts.SourceLeaseID = o.SourceAccessConditions.SourceLeaseAccessConditions.LeaseID - } - if o.SourceAccessConditions.SourceModifiedAccessConditions != nil { - sourceModifiedAccessConditions := &generated.SourceModifiedAccessConditions{ - SourceIfMatch: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfMatch, - SourceIfModifiedSince: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfModifiedSince, - SourceIfNoneMatch: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfNoneMatch, - SourceIfUnmodifiedSince: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfUnmodifiedSince, - } - return leaseAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions, createOpts - } - } - return leaseAccessConditions, modifiedAccessConditions, nil, createOpts -} - -// ===================================== PATH IMPORTS =========================================== - // UpdateAccessControlOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. type UpdateAccessControlOptions struct { //placeholder @@ -185,11 +126,11 @@ func (o *RemoveAccessControlOptions) format(ACL string) (*generated.PathClientSe }, mode } -type HTTPRange = exported.HTTPRange +// ===================================== PATH IMPORTS =========================================== // uploadFromReaderOptions identifies options used by the UploadBuffer and UploadFile functions. type uploadFromReaderOptions struct { - // ChunkSize specifies the chunk size to use in bytes; the default (and maximum size) is MaxUpdateRangeBytes. + // ChunkSize specifies the chunk size to use in bytes; the default (and maximum size) is MaxAppendBytes. ChunkSize int64 // Progress is a function that is invoked periodically as bytes are sent to the FileClient. // Note that the progress reporting is not always increasing; it can go down when retrying a request. @@ -206,7 +147,7 @@ type uploadFromReaderOptions struct { // UploadStreamOptions provides set of configurations for Client.UploadStream operation. type UploadStreamOptions struct { - // ChunkSize specifies the chunk size to use in bytes; the default (and maximum size) is MaxUpdateRangeBytes. + // ChunkSize specifies the chunk size to use in bytes; the default (and maximum size) is MaxAppendBytes. ChunkSize int64 // Concurrency indicates the maximum number of chunks to upload in parallel (default is 5) Concurrency uint16 @@ -427,10 +368,7 @@ func (o *DownloadStreamOptions) format() *blob.DownloadStreamOptions { downloadStreamOptions := &blob.DownloadStreamOptions{} if o.Range != nil { - downloadStreamOptions.Range = blob.HTTPRange{ - Offset: o.Range.Offset, - Count: o.Range.Count, - } + downloadStreamOptions.Range = *o.Range } if o.CPKInfo != nil { downloadStreamOptions.CPKInfo = &blob.CPKInfo{ @@ -442,7 +380,7 @@ func (o *DownloadStreamOptions) format() *blob.DownloadStreamOptions { downloadStreamOptions.RangeGetContentMD5 = o.RangeGetContentMD5 downloadStreamOptions.AccessConditions = exported.FormatBlobAccessConditions(o.AccessConditions) - downloadStreamOptions.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) + downloadStreamOptions.CPKScopeInfo = o.CPKScopeInfo return downloadStreamOptions } @@ -494,19 +432,12 @@ func (o *DownloadBufferOptions) format() *blob.DownloadBufferOptions { } downloadBufferOptions.AccessConditions = exported.FormatBlobAccessConditions(o.AccessConditions) - downloadBufferOptions.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) + downloadBufferOptions.CPKScopeInfo = o.CPKScopeInfo downloadBufferOptions.BlockSize = o.ChunkSize downloadBufferOptions.Progress = o.Progress downloadBufferOptions.Concurrency = o.Concurrency if o.RetryReaderOptionsPerChunk != nil { - newFunc := func(failureCount int32, lastError error, rnge blob.HTTPRange, willRetry bool) { - newRange := HTTPRange{ - Offset: rnge.Offset, - Count: rnge.Count, - } - o.RetryReaderOptionsPerChunk.OnFailedRead(failureCount, lastError, newRange, willRetry) - } - downloadBufferOptions.RetryReaderOptionsPerBlock.OnFailedRead = newFunc + downloadBufferOptions.RetryReaderOptionsPerBlock.OnFailedRead = o.RetryReaderOptionsPerChunk.OnFailedRead downloadBufferOptions.RetryReaderOptionsPerBlock.EarlyCloseAsError = o.RetryReaderOptionsPerChunk.EarlyCloseAsError downloadBufferOptions.RetryReaderOptionsPerBlock.MaxRetries = o.RetryReaderOptionsPerChunk.MaxRetries } @@ -560,19 +491,12 @@ func (o *DownloadFileOptions) format() *blob.DownloadFileOptions { } downloadFileOptions.AccessConditions = exported.FormatBlobAccessConditions(o.AccessConditions) - downloadFileOptions.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) + downloadFileOptions.CPKScopeInfo = o.CPKScopeInfo downloadFileOptions.BlockSize = o.ChunkSize downloadFileOptions.Progress = o.Progress downloadFileOptions.Concurrency = o.Concurrency if o.RetryReaderOptionsPerChunk != nil { - newFunc := func(failureCount int32, lastError error, rnge blob.HTTPRange, willRetry bool) { - newRange := HTTPRange{ - Offset: rnge.Offset, - Count: rnge.Count, - } - o.RetryReaderOptionsPerChunk.OnFailedRead(failureCount, lastError, newRange, willRetry) - } - downloadFileOptions.RetryReaderOptionsPerBlock.OnFailedRead = newFunc + downloadFileOptions.RetryReaderOptionsPerBlock.OnFailedRead = o.RetryReaderOptionsPerChunk.OnFailedRead downloadFileOptions.RetryReaderOptionsPerBlock.EarlyCloseAsError = o.RetryReaderOptionsPerChunk.EarlyCloseAsError downloadFileOptions.RetryReaderOptionsPerBlock.MaxRetries = o.RetryReaderOptionsPerChunk.MaxRetries } @@ -640,8 +564,16 @@ type SetExpiryTypeNever = exported.SetExpiryTypeNever // SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. type SetExpiryOptions = exported.SetExpiryOptions +type HTTPRange = exported.HTTPRange + // ================================= path imports ================================== +// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint +type DeleteOptions = path.DeleteOptions + +// RenameOptions contains the optional parameters when calling the Rename operation. +type RenameOptions = path.RenameOptions + // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method type GetPropertiesOptions = path.GetPropertiesOptions @@ -685,4 +617,4 @@ type ModifiedAccessConditions = path.ModifiedAccessConditions type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions // CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. -type CPKScopeInfo path.CPKScopeInfo +type CPKScopeInfo = path.CPKScopeInfo diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index c0c7ee5b8086..6c21c0ed364e 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -282,7 +282,8 @@ func (fs *Client) NewListPathsPager(recursive bool, options *ListPathsOptions) * if !runtime.HasStatusCode(resp, http.StatusOK) { return ListPathsSegmentResponse{}, runtime.NewResponseError(resp) } - return fs.generatedFSClientWithDFS().ListPathsHandleResponse(resp) + newResp, err := fs.generatedFSClientWithDFS().ListPathsHandleResponse(resp) + return newResp, exported.ConvertToDFSError(err) }, }) } @@ -317,7 +318,8 @@ func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *ru if !runtime.HasStatusCode(resp, http.StatusOK) { return ListDeletedPathsSegmentResponse{}, runtime.NewResponseError(resp) } - return fs.generatedFSClientWithDFS().ListBlobHierarchySegmentHandleResponse(resp) + newResp, err := fs.generatedFSClientWithDFS().ListBlobHierarchySegmentHandleResponse(resp) + return newResp, exported.ConvertToDFSError(err) }, }) } diff --git a/sdk/storage/azdatalake/internal/exported/exported.go b/sdk/storage/azdatalake/internal/exported/exported.go index ab0c5ebea4cf..0dea8e21223c 100644 --- a/sdk/storage/azdatalake/internal/exported/exported.go +++ b/sdk/storage/azdatalake/internal/exported/exported.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "strconv" "strings" ) @@ -19,10 +20,7 @@ const SnapshotTimeFormat = "2006-01-02T15:04:05.0000000Z07:00" // HTTPRange defines a range of bytes within an HTTP resource, starting at offset and // ending at offset+count. A zero-value HTTPRange indicates the entire resource. An HTTPRange // which has an offset but no zero value count indicates from the offset to the resource's end. -type HTTPRange struct { - Offset int64 - Count int64 -} +type HTTPRange = blob.HTTPRange // FormatHTTPRange converts an HTTPRange to its string format. func FormatHTTPRange(r HTTPRange) *string { diff --git a/sdk/storage/azdatalake/internal/generated/autorest.md b/sdk/storage/azdatalake/internal/generated/autorest.md index e5184eb7f1df..260f00f66118 100644 --- a/sdk/storage/azdatalake/internal/generated/autorest.md +++ b/sdk/storage/azdatalake/internal/generated/autorest.md @@ -76,8 +76,23 @@ directive: transform: >- return $. replace(/func \(client \*ServiceClient\) NewListFileSystemsPager\(.+\/\/ listFileSystemsCreateRequest creates the ListFileSystems request/s, `//\n// ListFileSystemsCreateRequest creates the ListFileSystems request`). - replace(/\(client \*ServiceClient\) listFileSystemsCreateRequest\(/, `(client *FileSystemClient) ListFileSystemsCreateRequest(`). - replace(/\(client \*ServiceClient\) listFileSystemsHandleResponse\(/, `(client *FileSystemClient) ListFileSystemsHandleResponse(`); + replace(/\(client \*ServiceClient\) listFileSystemsCreateRequest\(/, `(client *ServiceClient) ListFileSystemsCreateRequest(`). + replace(/\(client \*ServiceClient\) listFileSystemsHandleResponse\(/, `(client *ServiceClient) ListFileSystemsHandleResponse(`); +``` + + +### Remove pager methods and export various generated methods in path client + +``` yaml +directive: + - from: zz_path_client.go + where: $ + transform: >- + return $. + replace(/\(client \*PathClient\) setAccessControlRecursiveCreateRequest\(/, `(client *PathClient) SetAccessControlRecursiveCreateRequest(`). + replace(/\(client \*PathClient\) setAccessControlRecursiveHandleResponse\(/, `(client *PathClient) SetAccessControlRecursiveHandleResponse(`). + replace(/setAccessControlRecursiveCreateRequest/g, 'SetAccessControlRecursiveCreateRequest'). + replace(/setAccessControlRecursiveHandleResponse/g, 'SetAccessControlRecursiveHandleResponse'); ``` ### Fix EncryptionAlgorithm diff --git a/sdk/storage/azdatalake/internal/generated/zz_path_client.go b/sdk/storage/azdatalake/internal/generated/zz_path_client.go index 4f3c3b3ba19f..f0547cb91e1a 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_path_client.go +++ b/sdk/storage/azdatalake/internal/generated/zz_path_client.go @@ -1124,7 +1124,7 @@ func (client *PathClient) setAccessControlHandleResponse(resp *http.Response) (P // - options - PathClientSetAccessControlRecursiveOptions contains the optional parameters for the PathClient.SetAccessControlRecursive // method. func (client *PathClient) SetAccessControlRecursive(ctx context.Context, mode PathSetAccessControlRecursiveMode, options *PathClientSetAccessControlRecursiveOptions) (PathClientSetAccessControlRecursiveResponse, error) { - req, err := client.setAccessControlRecursiveCreateRequest(ctx, mode, options) + req, err := client.SetAccessControlRecursiveCreateRequest(ctx, mode, options) if err != nil { return PathClientSetAccessControlRecursiveResponse{}, err } @@ -1135,11 +1135,11 @@ func (client *PathClient) SetAccessControlRecursive(ctx context.Context, mode Pa if !runtime.HasStatusCode(resp, http.StatusOK) { return PathClientSetAccessControlRecursiveResponse{}, runtime.NewResponseError(resp) } - return client.setAccessControlRecursiveHandleResponse(resp) + return client.SetAccessControlRecursiveHandleResponse(resp) } -// setAccessControlRecursiveCreateRequest creates the SetAccessControlRecursive request. -func (client *PathClient) setAccessControlRecursiveCreateRequest(ctx context.Context, mode PathSetAccessControlRecursiveMode, options *PathClientSetAccessControlRecursiveOptions) (*policy.Request, error) { +// SetAccessControlRecursiveCreateRequest creates the SetAccessControlRecursive request. +func (client *PathClient) SetAccessControlRecursiveCreateRequest(ctx context.Context, mode PathSetAccessControlRecursiveMode, options *PathClientSetAccessControlRecursiveOptions) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) if err != nil { return nil, err @@ -1171,8 +1171,8 @@ func (client *PathClient) setAccessControlRecursiveCreateRequest(ctx context.Con return req, nil } -// setAccessControlRecursiveHandleResponse handles the SetAccessControlRecursive response. -func (client *PathClient) setAccessControlRecursiveHandleResponse(resp *http.Response) (PathClientSetAccessControlRecursiveResponse, error) { +// SetAccessControlRecursiveHandleResponse handles the SetAccessControlRecursive response. +func (client *PathClient) SetAccessControlRecursiveHandleResponse(resp *http.Response) (PathClientSetAccessControlRecursiveResponse, error) { result := PathClientSetAccessControlRecursiveResponse{} if val := resp.Header.Get("Date"); val != "" { date, err := time.Parse(time.RFC1123, val) diff --git a/sdk/storage/azdatalake/internal/generated/zz_service_client.go b/sdk/storage/azdatalake/internal/generated/zz_service_client.go index f4322dd4f3fd..4c6e81408b18 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_service_client.go +++ b/sdk/storage/azdatalake/internal/generated/zz_service_client.go @@ -34,7 +34,7 @@ type ServiceClient struct { // method. // // ListFileSystemsCreateRequest creates the ListFileSystems request. -func (client *FileSystemClient) ListFileSystemsCreateRequest(ctx context.Context, options *ServiceClientListFileSystemsOptions) (*policy.Request, error) { +func (client *ServiceClient) ListFileSystemsCreateRequest(ctx context.Context, options *ServiceClientListFileSystemsOptions) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) if err != nil { return nil, err @@ -63,7 +63,7 @@ func (client *FileSystemClient) ListFileSystemsCreateRequest(ctx context.Context } // listFileSystemsHandleResponse handles the ListFileSystems response. -func (client *FileSystemClient) ListFileSystemsHandleResponse(resp *http.Response) (ServiceClientListFileSystemsResponse, error) { +func (client *ServiceClient) ListFileSystemsHandleResponse(resp *http.Response) (ServiceClientListFileSystemsResponse, error) { result := ServiceClientListFileSystemsResponse{} if val := resp.Header.Get("Date"); val != "" { date, err := time.Parse(time.RFC1123, val) diff --git a/sdk/storage/azdatalake/internal/path/models.go b/sdk/storage/azdatalake/internal/path/models.go index f476fcae518f..112dda4c922c 100644 --- a/sdk/storage/azdatalake/internal/path/models.go +++ b/sdk/storage/azdatalake/internal/path/models.go @@ -15,6 +15,59 @@ import ( "time" ) +// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint +type DeleteOptions struct { + // AccessConditions contains parameters for accessing the file. + AccessConditions *AccessConditions +} + +func FormatDeleteOptions(o *DeleteOptions, recursive bool) (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, *generated.PathClientDeleteOptions) { + deleteOpts := &generated.PathClientDeleteOptions{ + Recursive: &recursive, + } + if o == nil { + return nil, nil, deleteOpts + } + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) + return leaseAccessConditions, modifiedAccessConditions, deleteOpts +} + +// RenameOptions contains the optional parameters when calling the Rename operation. +type RenameOptions struct { + // SourceAccessConditions identifies the source path access conditions. + SourceAccessConditions *SourceAccessConditions + // AccessConditions contains parameters for accessing the file. + AccessConditions *AccessConditions +} + +func FormatRenameOptions(o *RenameOptions, path string) (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, *generated.SourceModifiedAccessConditions, *generated.PathClientCreateOptions) { + // we don't need sourceModAccCond since this is not rename + mode := generated.PathRenameModeLegacy + createOpts := &generated.PathClientCreateOptions{ + Mode: &mode, + RenameSource: &path, + } + if o == nil { + return nil, nil, nil, createOpts + } + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) + if o.SourceAccessConditions != nil { + if o.SourceAccessConditions.SourceLeaseAccessConditions != nil { + createOpts.SourceLeaseID = o.SourceAccessConditions.SourceLeaseAccessConditions.LeaseID + } + if o.SourceAccessConditions.SourceModifiedAccessConditions != nil { + sourceModifiedAccessConditions := &generated.SourceModifiedAccessConditions{ + SourceIfMatch: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfMatch, + SourceIfModifiedSince: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfModifiedSince, + SourceIfNoneMatch: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfNoneMatch, + SourceIfUnmodifiedSince: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfUnmodifiedSince, + } + return leaseAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions, createOpts + } + } + return leaseAccessConditions, modifiedAccessConditions, nil, createOpts +} + // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method type GetPropertiesOptions struct { AccessConditions *AccessConditions @@ -173,7 +226,6 @@ func FormatBlobHTTPHeaders(o *HTTPHeaders) *blob.HTTPHeaders { } func FormatPathHTTPHeaders(o *HTTPHeaders) *generated.PathHTTPHeaders { - // TODO: will be used for file related ops, like append if o == nil { return nil } @@ -239,4 +291,4 @@ type ModifiedAccessConditions = exported.ModifiedAccessConditions type SourceModifiedAccessConditions = exported.SourceModifiedAccessConditions // CPKScopeInfo contains a group of parameters for the Client.SetMetadata() method. -type CPKScopeInfo blob.CPKScopeInfo +type CPKScopeInfo = blob.CPKScopeInfo diff --git a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go index bd1607b2fec4..20c2d683daa5 100644 --- a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go +++ b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go @@ -8,6 +8,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/directory" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/file" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/service" @@ -140,6 +141,23 @@ func GetFileClient(fsName, fName string, t *testing.T, accountType TestAccountTy return fileClient, err } +func GetDirClient(fsName, dirName string, t *testing.T, accountType TestAccountType, options *directory.ClientOptions) (*directory.Client, error) { + if options == nil { + options = &directory.ClientOptions{} + } + + SetClientOptions(t, &options.ClientOptions) + + cred, err := GetGenericSharedKeyCredential(accountType) + if err != nil { + return nil, err + } + + dirClient, err := directory.NewClientWithSharedKeyCredential("https://"+cred.AccountName()+".dfs.core.windows.net/"+fsName+"/"+dirName, cred, options) + + return dirClient, err +} + func ServiceGetFilesystemClient(filesystemName string, s *service.Client) *filesystem.Client { return s.NewFilesystemClient(filesystemName) } @@ -154,6 +172,11 @@ func DeleteFile(ctx context.Context, _require *require.Assertions, fileClient *f _require.Nil(err) } +func DeleteDir(ctx context.Context, _require *require.Assertions, dirClient *directory.Client) { + _, err := dirClient.Delete(ctx, nil) + _require.Nil(err) +} + func GetGenericConnectionString(accountType TestAccountType) (*string, error) { accountName, accountKey := GetGenericAccountInfo(accountType) if accountName == "" || accountKey == "" { diff --git a/sdk/storage/azdatalake/internal/testcommon/common.go b/sdk/storage/azdatalake/internal/testcommon/common.go index 36af75cc92a7..e5451ba6a38b 100644 --- a/sdk/storage/azdatalake/internal/testcommon/common.go +++ b/sdk/storage/azdatalake/internal/testcommon/common.go @@ -18,6 +18,7 @@ import ( const ( FilesystemPrefix = "gofs" FilePrefix = "gotestfile" + DirPrefix = "gotestdir" DefaultData = "Godatalakedata" InvalidHeaderErrorSubstring = "invalid header field" // error thrown by the http client ) @@ -30,6 +31,10 @@ func GenerateFileName(testName string) string { return FilePrefix + GenerateEntityName(testName) } +func GenerateDirName(testName string) string { + return DirPrefix + GenerateEntityName(testName) +} + func GenerateEntityName(testName string) string { return strings.ReplaceAll(strings.ReplaceAll(strings.ToLower(testName), "/", ""), "test", "") }