diff --git a/storage/2023-11-03/file/directories/delete.go b/storage/2023-11-03/file/directories/delete.go index 35b7298..eeae2c2 100644 --- a/storage/2023-11-03/file/directories/delete.go +++ b/storage/2023-11-03/file/directories/delete.go @@ -1,12 +1,17 @@ package directories import ( + "bytes" "context" + "encoding/xml" "fmt" + "io" "net/http" "strings" + "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" ) type DeleteResponse struct { @@ -32,6 +37,30 @@ func (c Client) Delete(ctx context.Context, shareName, path string) (result Dele return } + // Retry the directory deletion if the directory is not empty (deleted files take a little while to disappear) + retryFunc := func(resp *http.Response, _ *odata.OData) (bool, error) { + if resp != nil { + if response.WasStatusCode(resp, http.StatusConflict) { + // TODO: move this error response parsing to a common helper function + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return false, fmt.Errorf("could not parse response body") + } + resp.Body.Close() + respBody = bytes.TrimPrefix(respBody, []byte("\xef\xbb\xbf")) + res := ErrorResponse{} + if err = xml.Unmarshal(respBody, &res); err != nil { + return false, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(respBody)) + if res.Code != nil { + return strings.Contains(*res.Code, "DirectoryNotEmpty"), nil + } + } + } + return false, nil + } + opts := client.RequestOptions{ ContentType: "application/xml; charset=utf-8", ExpectedStatusCodes: []int{ @@ -40,6 +69,7 @@ func (c Client) Delete(ctx context.Context, shareName, path string) (result Dele HttpMethod: http.MethodDelete, OptionsObject: directoriesOptions{}, Path: fmt.Sprintf("/%s/%s", shareName, path), + RetryFunc: retryFunc, } req, err := c.Client.NewRequest(ctx, opts) diff --git a/storage/2023-11-03/file/directories/models.go b/storage/2023-11-03/file/directories/models.go new file mode 100644 index 0000000..85c3bde --- /dev/null +++ b/storage/2023-11-03/file/directories/models.go @@ -0,0 +1,9 @@ +package directories + +import "encoding/xml" + +type ErrorResponse struct { + XMLName xml.Name `xml:"Error"` + Code *string `xml:"Code"` + Message *string `xml:"Message"` +} diff --git a/storage/2023-11-03/file/files/delete.go b/storage/2023-11-03/file/files/delete.go index f3841fa..90c7737 100644 --- a/storage/2023-11-03/file/files/delete.go +++ b/storage/2023-11-03/file/files/delete.go @@ -32,7 +32,7 @@ func (c Client) Delete(ctx context.Context, shareName, path, fileName string) (r } if path != "" { - path = fmt.Sprintf("/%s/", path) + path = fmt.Sprintf("%s/", path) } opts := client.RequestOptions{ diff --git a/storage/2023-11-03/file/files/metadata_set.go b/storage/2023-11-03/file/files/metadata_set.go index 3a51a10..e1ba9d0 100644 --- a/storage/2023-11-03/file/files/metadata_set.go +++ b/storage/2023-11-03/file/files/metadata_set.go @@ -42,7 +42,7 @@ func (c Client) SetMetaData(ctx context.Context, shareName, path, fileName strin } if path != "" { - path = fmt.Sprintf("/%s/", path) + path = fmt.Sprintf("%s/", path) } opts := client.RequestOptions{ diff --git a/storage/2023-11-03/file/files/properties_get.go b/storage/2023-11-03/file/files/properties_get.go index 927ec63..129ad24 100644 --- a/storage/2023-11-03/file/files/properties_get.go +++ b/storage/2023-11-03/file/files/properties_get.go @@ -50,7 +50,7 @@ func (c Client) GetProperties(ctx context.Context, shareName, path, fileName str } if path != "" { - path = fmt.Sprintf("/%s/", path) + path = fmt.Sprintf("%s/", path) } opts := client.RequestOptions{ diff --git a/storage/2023-11-03/file/files/properties_set.go b/storage/2023-11-03/file/files/properties_set.go index 83bd841..18ecd83 100644 --- a/storage/2023-11-03/file/files/properties_set.go +++ b/storage/2023-11-03/file/files/properties_set.go @@ -89,7 +89,7 @@ func (c Client) SetProperties(ctx context.Context, shareName, path, fileName str } if path != "" { - path = fmt.Sprintf("/%s/", path) + path = fmt.Sprintf("%s/", path) } opts := client.RequestOptions{ diff --git a/storage/2023-11-03/file/files/range_put.go b/storage/2023-11-03/file/files/range_put.go index 58e6f9b..c799ffd 100644 --- a/storage/2023-11-03/file/files/range_put.go +++ b/storage/2023-11-03/file/files/range_put.go @@ -65,7 +65,7 @@ func (c Client) PutByteRange(ctx context.Context, shareName, path, fileName stri } if path != "" { - path = fmt.Sprintf("/%s/", path) + path = fmt.Sprintf("%s/", path) } opts := client.RequestOptions{ diff --git a/storage/2023-11-03/file/files/resource_id.go b/storage/2023-11-03/file/files/resource_id.go index 4928897..63d5c55 100644 --- a/storage/2023-11-03/file/files/resource_id.go +++ b/storage/2023-11-03/file/files/resource_id.go @@ -37,7 +37,11 @@ func NewFileID(accountId accounts.AccountId, shareName, directoryPath, fileName } func (b FileId) ID() string { - return fmt.Sprintf("%s/%s/%s/%s", b.AccountId.ID(), b.ShareName, b.DirectoryPath, b.FileName) + path := "" + if b.DirectoryPath != "" { + path = fmt.Sprintf("%s/", b.DirectoryPath) + } + return fmt.Sprintf("%s/%s/%s%s", b.AccountId.ID(), b.ShareName, path, b.FileName) } func (b FileId) String() string { @@ -72,8 +76,8 @@ func ParseFileID(input, domainSuffix string) (*FileId, error) { path := strings.TrimPrefix(uri.Path, "/") segments := strings.Split(path, "/") - if len(segments) < 3 { - return nil, fmt.Errorf("expected the path to contain at least 3 segments but got %d", len(segments)) + if len(segments) < 2 { + return nil, fmt.Errorf("expected the path to contain at least 2 segments but got %d", len(segments)) } shareName := segments[0] directoryPath := strings.Join(segments[1:len(segments)-1], "/")